1. Project Clover database Sat Apr 27 2024 21:29:13 CDT
  2. Package net.bytebuddy.dynamic.scaffold

File TypeWriter.java

 

Coverage histogram

../../../../img/srcFileCovDistChart9.png
81% of files have more coverage

Code metrics

192
622
280
38
3,601
2,211
422
0.68
2.22
7.37
1.51

Classes

Class Line # Actions
TypeWriter 49 0 - 0 0
-1.0 -
TypeWriter.FieldPool 68 0 - 0 0
-1.0 -
TypeWriter.FieldPool.Record 85 0 - 0 0
-1.0 -
TypeWriter.FieldPool.Record.ForImplicitField 135 12 0% 10 0
1.0100%
TypeWriter.FieldPool.Record.ForExplicitField 211 22 0% 16 2
0.9523809695.2%
TypeWriter.MethodPool 312 0 - 0 0
-1.0 -
TypeWriter.MethodPool.Record 327 0 - 0 0
-1.0 -
TypeWriter.MethodPool.Record.Sort 382 5 0% 4 2
0.777777877.8%
TypeWriter.MethodPool.Record.ForNonDefinedMethod 447 6 0% 7 0
1.0100%
TypeWriter.MethodPool.Record.ForDefinedMethod 493 8 0% 2 0
1.0100%
TypeWriter.MethodPool.Record.ForDefinedMethod.WithBody 516 22 0% 13 0
1.0100%
TypeWriter.MethodPool.Record.ForDefinedMethod.WithoutBody 615 16 0% 12 0
1.0100%
TypeWriter.MethodPool.Record.ForDefinedMethod.WithAnnotationDefaultValue 691 23 0% 13 0
1.0100%
TypeWriter.MethodPool.Record.ForDefinedMethod.OfVisibilityBridge 787 25 0% 14 0
1.0100%
TypeWriter.MethodPool.Record.ForDefinedMethod.OfVisibilityBridge.VisibilityBridge 912 11 0% 10 2
0.904761990.5%
TypeWriter.MethodPool.Record.AccessBridgeWrapper 988 34 0% 18 2
0.962264296.2%
TypeWriter.MethodPool.Record.AccessBridgeWrapper.AccessorBridge 1147 12 0% 10 2
0.9090909490.9%
TypeWriter.MethodPool.Record.AccessBridgeWrapper.BridgeTarget 1226 11 0% 10 8
0.6190476461.9%
TypeWriter.Default 1303 58 0% 14 9
0.87587.5%
TypeWriter.Default.ValidatingClassVisitor 1693 78 0% 34 0
1.0100%
TypeWriter.Default.ValidatingClassVisitor.Constraint 1863 0 - 0 0
-1.0 -
TypeWriter.Default.ValidatingClassVisitor.Constraint.ForClass 1948 5 0% 15 3
0.8585%
TypeWriter.Default.ValidatingClassVisitor.Constraint.ForPackageType 2046 7 0% 14 9
0.608695660.9%
TypeWriter.Default.ValidatingClassVisitor.Constraint.ForInterface 2127 11 0% 22 12
0.6470588464.7%
TypeWriter.Default.ValidatingClassVisitor.Constraint.ForAnnotation 2233 13 0% 23 10
0.736842173.7%
TypeWriter.Default.ValidatingClassVisitor.Constraint.ForClassFileVersion 2341 28 0% 33 19
0.716417971.6%
TypeWriter.Default.ValidatingClassVisitor.Constraint.Compound 2464 26 0% 15 3
0.926829392.7%
TypeWriter.Default.ValidatingClassVisitor.ValidatingFieldVisitor 2592 4 0% 3 0
1.0100%
TypeWriter.Default.ValidatingClassVisitor.ValidatingMethodVisitor 2620 25 0% 13 3
0.9210526392.1%
TypeWriter.Default.FrameComputingClassWriter 2698 16 0% 9 1
0.9642857396.4%
TypeWriter.Default.ForInlining 2759 30 0% 14 3
0.936170293.6%
TypeWriter.Default.ForInlining.TypeInitializerDelegate 2940 11 0% 11 3
0.869565287%
TypeWriter.Default.ForInlining.RedefinitionClassVisitor 3019 49 0% 24 4
0.9523809695.2%
TypeWriter.Default.ForInlining.RedefinitionClassVisitor.AttributeObtainingFieldVisitor 3221 7 0% 7 4
0.7575%
TypeWriter.Default.ForInlining.RedefinitionClassVisitor.CodePreservingMethodVisitor 3272 15 0% 12 6
0.806451680.6%
TypeWriter.Default.ForInlining.RedefinitionClassVisitor.AttributeObtainingMethodVisitor 3366 12 0% 11 16
0.384615438.5%
TypeWriter.Default.ForInlining.RedefinitionClassVisitor.TypeInitializerInjection 3442 5 0% 5 0
1.0100%
TypeWriter.Default.ForCreation 3493 15 0% 4 1
0.9595%
 

Contributing tests

This file is covered by 1238 tests. .

Source view

1    package net.bytebuddy.dynamic.scaffold;
2   
3    import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4    import net.bytebuddy.ClassFileVersion;
5    import net.bytebuddy.asm.AsmVisitorWrapper;
6    import net.bytebuddy.description.annotation.AnnotationList;
7    import net.bytebuddy.description.field.FieldDescription;
8    import net.bytebuddy.description.method.MethodDescription;
9    import net.bytebuddy.description.method.MethodList;
10    import net.bytebuddy.description.method.ParameterDescription;
11    import net.bytebuddy.description.method.ParameterList;
12    import net.bytebuddy.description.type.PackageDescription;
13    import net.bytebuddy.description.type.TypeDescription;
14    import net.bytebuddy.description.type.TypeList;
15    import net.bytebuddy.dynamic.ClassFileLocator;
16    import net.bytebuddy.dynamic.DynamicType;
17    import net.bytebuddy.dynamic.scaffold.inline.MethodRebaseResolver;
18    import net.bytebuddy.implementation.Implementation;
19    import net.bytebuddy.implementation.LoadedTypeInitializer;
20    import net.bytebuddy.implementation.attribute.*;
21    import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
22    import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
23    import net.bytebuddy.implementation.bytecode.StackManipulation;
24    import net.bytebuddy.implementation.bytecode.assign.TypeCasting;
25    import net.bytebuddy.implementation.bytecode.member.MethodInvocation;
26    import net.bytebuddy.implementation.bytecode.member.MethodReturn;
27    import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess;
28    import net.bytebuddy.pool.TypePool;
29    import net.bytebuddy.utility.CompoundList;
30    import net.bytebuddy.utility.RandomString;
31    import org.objectweb.asm.*;
32    import org.objectweb.asm.commons.ClassRemapper;
33    import org.objectweb.asm.commons.SimpleRemapper;
34   
35    import java.io.File;
36    import java.io.FileOutputStream;
37    import java.io.IOException;
38    import java.io.OutputStream;
39    import java.util.*;
40    import java.util.logging.Logger;
41   
42    import static net.bytebuddy.matcher.ElementMatchers.is;
43   
44    /**
45    * A type writer is a utility for writing an actual class file using the ASM library.
46    *
47    * @param <T> The best known loaded type for the dynamically created type.
48    */
 
49    public interface TypeWriter<T> {
50   
51    /**
52    * A system property that indicates a folder for Byte Buddy to dump class files of all types that it creates.
53    * If this property is not set, Byte Buddy does not dump any class files. This property is only read a single
54    * time which is why it must be set on application start-up.
55    */
56    String DUMP_PROPERTY = "net.bytebuddy.dump";
57   
58    /**
59    * Creates the dynamic type that is described by this type writer.
60    *
61    * @return An unloaded dynamic type that describes the created type.
62    */
63    DynamicType.Unloaded<T> make();
64   
65    /**
66    * An field pool that allows a lookup for how to implement a field.
67    */
 
68    interface FieldPool {
69   
70    /**
71    * Returns the field attribute appender that matches a given field description or a default field
72    * attribute appender if no appender was registered for the given field.
73    *
74    * @param fieldDescription The field description of interest.
75    * @return The registered field attribute appender for the given field or the default appender if no such
76    * appender was found.
77    */
78    Record target(FieldDescription fieldDescription);
79   
80    /**
81    * An entry of a field pool that describes how a field is implemented.
82    *
83    * @see net.bytebuddy.dynamic.scaffold.TypeWriter.FieldPool
84    */
 
85    interface Record {
86   
87    /**
88    * Determines if this record is implicit, i.e is not defined by a {@link FieldPool}.
89    *
90    * @return {@code true} if this record is implicit.
91    */
92    boolean isImplicit();
93   
94    /**
95    * Returns the field that this record represents.
96    *
97    * @return The field that this record represents.
98    */
99    FieldDescription getField();
100   
101    /**
102    * Returns the field attribute appender for a given field.
103    *
104    * @return The attribute appender to be applied on the given field.
105    */
106    FieldAttributeAppender getFieldAppender();
107   
108    /**
109    * Resolves the default value that this record represents. This is not possible for implicit records.
110    *
111    * @param defaultValue The default value that was defined previously or {@code null} if no default value is defined.
112    * @return The default value for the represented field or {@code null} if no default value is to be defined.
113    */
114    Object resolveDefault(Object defaultValue);
115   
116    /**
117    * Writes this entry to a given class visitor.
118    *
119    * @param classVisitor The class visitor to which this entry is to be written to.
120    * @param annotationValueFilterFactory The annotation value filter factory to apply when writing annotations.
121    */
122    void apply(ClassVisitor classVisitor, AnnotationValueFilter.Factory annotationValueFilterFactory);
123   
124    /**
125    * Applies this record to a field visitor. This is not possible for implicit records.
126    *
127    * @param fieldVisitor The field visitor onto which this record is to be applied.
128    * @param annotationValueFilterFactory The annotation value filter factory to use for annotations.
129    */
130    void apply(FieldVisitor fieldVisitor, AnnotationValueFilter.Factory annotationValueFilterFactory);
131   
132    /**
133    * A record for a simple field without a default value where all of the field's declared annotations are appended.
134    */
 
135    class ForImplicitField implements Record {
136   
137    /**
138    * The implemented field.
139    */
140    private final FieldDescription fieldDescription;
141   
142    /**
143    * Creates a new record for a simple field.
144    *
145    * @param fieldDescription The described field.
146    */
 
147  1238 toggle public ForImplicitField(FieldDescription fieldDescription) {
148  1238 this.fieldDescription = fieldDescription;
149    }
150   
 
151  1026 toggle @Override
152    public boolean isImplicit() {
153  1026 return true;
154    }
155   
 
156  1 toggle @Override
157    public FieldDescription getField() {
158  1 return fieldDescription;
159    }
160   
 
161  2 toggle @Override
162    public FieldAttributeAppender getFieldAppender() {
163  2 throw new IllegalStateException("An implicit field record does not expose a field appender: " + this);
164    }
165   
 
166  2 toggle @Override
167    public Object resolveDefault(Object defaultValue) {
168  2 throw new IllegalStateException("An implicit field record does not expose a default value: " + this);
169    }
170   
 
171  200 toggle @Override
172    public void apply(ClassVisitor classVisitor, AnnotationValueFilter.Factory annotationValueFilterFactory) {
173  200 FieldVisitor fieldVisitor = classVisitor.visitField(fieldDescription.getActualModifiers(),
174    fieldDescription.getInternalName(),
175    fieldDescription.getDescriptor(),
176    fieldDescription.getGenericSignature(),
177    FieldDescription.NO_DEFAULT_VALUE);
178  200 FieldAttributeAppender.ForInstrumentedField.INSTANCE.apply(fieldVisitor,
179    fieldDescription,
180    annotationValueFilterFactory.on(fieldDescription));
181  200 fieldVisitor.visitEnd();
182    }
183   
 
184  4 toggle @Override
185    public void apply(FieldVisitor fieldVisitor, AnnotationValueFilter.Factory annotationValueFilterFactory) {
186  4 throw new IllegalStateException("An implicit field record is not intended for partial application: " + this);
187    }
188   
 
189  5 toggle @Override
190    public boolean equals(Object other) {
191  5 return this == other || !(other == null || getClass() != other.getClass())
192    && fieldDescription.equals(((ForImplicitField) other).fieldDescription);
193    }
194   
 
195  3 toggle @Override
196    public int hashCode() {
197  3 return fieldDescription.hashCode();
198    }
199   
 
200  11 toggle @Override
201    public String toString() {
202  11 return "TypeWriter.FieldPool.Record.ForImplicitField{" +
203    "fieldDescription=" + fieldDescription +
204    '}';
205    }
206    }
207   
208    /**
209    * A record for a rich field with attributes and a potential default value.
210    */
 
211    class ForExplicitField implements Record {
212   
213    /**
214    * The attribute appender for the field.
215    */
216    private final FieldAttributeAppender attributeAppender;
217   
218    /**
219    * The field's default value.
220    */
221    private final Object defaultValue;
222   
223    /**
224    * The implemented field.
225    */
226    private final FieldDescription fieldDescription;
227   
228    /**
229    * Creates a record for a rich field.
230    *
231    * @param attributeAppender The attribute appender for the field.
232    * @param defaultValue The field's default value.
233    * @param fieldDescription The implemented field.
234    */
 
235  588 toggle public ForExplicitField(FieldAttributeAppender attributeAppender, Object defaultValue, FieldDescription fieldDescription) {
236  588 this.attributeAppender = attributeAppender;
237  588 this.defaultValue = defaultValue;
238  588 this.fieldDescription = fieldDescription;
239    }
240   
 
241  8 toggle @Override
242    public boolean isImplicit() {
243  8 return false;
244    }
245   
 
246  7 toggle @Override
247    public FieldDescription getField() {
248  7 return fieldDescription;
249    }
250   
 
251  2 toggle @Override
252    public FieldAttributeAppender getFieldAppender() {
253  2 return attributeAppender;
254    }
255   
 
256  579 toggle @Override
257    public Object resolveDefault(Object defaultValue) {
258  579 return this.defaultValue == null
259    ? defaultValue
260    : this.defaultValue;
261    }
262   
 
263  571 toggle @Override
264    public void apply(ClassVisitor classVisitor, AnnotationValueFilter.Factory annotationValueFilterFactory) {
265  571 FieldVisitor fieldVisitor = classVisitor.visitField(fieldDescription.getActualModifiers(),
266    fieldDescription.getInternalName(),
267    fieldDescription.getDescriptor(),
268    fieldDescription.getGenericSignature(),
269    resolveDefault(FieldDescription.NO_DEFAULT_VALUE));
270  563 attributeAppender.apply(fieldVisitor, fieldDescription, annotationValueFilterFactory.on(fieldDescription));
271  562 fieldVisitor.visitEnd();
272    }
273   
 
274  7 toggle @Override
275    public void apply(FieldVisitor fieldVisitor, AnnotationValueFilter.Factory annotationValueFilterFactory) {
276  7 attributeAppender.apply(fieldVisitor, fieldDescription, annotationValueFilterFactory.on(fieldDescription));
277    }
278   
 
279  7 toggle @Override
280    public boolean equals(Object other) {
281  1 if (this == other) return true;
282  2 if (other == null || getClass() != other.getClass()) return false;
283  4 ForExplicitField that = (ForExplicitField) other;
284  4 return attributeAppender.equals(that.attributeAppender)
285  3 && !(defaultValue != null ? !defaultValue.equals(that.defaultValue) : that.defaultValue != null)
286    && fieldDescription.equals(that.fieldDescription);
287    }
288   
 
289  5 toggle @Override
290    public int hashCode() {
291  5 int result = attributeAppender.hashCode();
292  5 result = 31 * result + (defaultValue != null ? defaultValue.hashCode() : 0);
293  5 result = 31 * result + fieldDescription.hashCode();
294  5 return result;
295    }
296   
 
297  5 toggle @Override
298    public String toString() {
299  5 return "TypeWriter.FieldPool.Record.ForExplicitField{" +
300    "attributeAppender=" + attributeAppender +
301    ", defaultValue=" + defaultValue +
302    ", fieldDescription=" + fieldDescription +
303    '}';
304    }
305    }
306    }
307    }
308   
309    /**
310    * An method pool that allows a lookup for how to implement a method.
311    */
 
312    interface MethodPool {
313   
314    /**
315    * Looks up a handler entry for a given method.
316    *
317    * @param methodDescription The method being processed.
318    * @return A handler entry for the given method.
319    */
320    Record target(MethodDescription methodDescription);
321   
322    /**
323    * An entry of a method pool that describes how a method is implemented.
324    *
325    * @see net.bytebuddy.dynamic.scaffold.TypeWriter.MethodPool
326    */
 
327    interface Record {
328   
329    /**
330    * Returns the sort of this method instrumentation.
331    *
332    * @return The sort of this method instrumentation.
333    */
334    Sort getSort();
335   
336    /**
337    * Returns the method that is implemented where the returned method resembles a potential transformation. An implemented
338    * method is only defined if a method is not {@link Record.Sort#SKIPPED}.
339    *
340    * @return The implemented method.
341    */
342    MethodDescription getMethod();
343   
344    /**
345    * Prepends the given method appender to this entry.
346    *
347    * @param byteCodeAppender The byte code appender to prepend.
348    * @return This entry with the given code prepended.
349    */
350    Record prepend(ByteCodeAppender byteCodeAppender);
351   
352    /**
353    * Applies this method entry. This method can always be called and might be a no-op.
354    *
355    * @param classVisitor The class visitor to which this entry should be applied.
356    * @param implementationContext The implementation context to which this entry should be applied.
357    * @param annotationValueFilterFactory The annotation value filter factory to apply when writing annotations.
358    */
359    void apply(ClassVisitor classVisitor, Implementation.Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory);
360   
361    /**
362    * Applies the head of this entry. Applying an entry is only possible if a method is defined, i.e. the sort of this entry is not
363    * {@link Record.Sort#SKIPPED}.
364    *
365    * @param methodVisitor The method visitor to which this entry should be applied.
366    */
367    void applyHead(MethodVisitor methodVisitor);
368   
369    /**
370    * Applies the body of this entry. Applying the body of an entry is only possible if a method is implemented, i.e. the sort of this
371    * entry is {@link Record.Sort#IMPLEMENTED}.
372    *
373    * @param methodVisitor The method visitor to which this entry should be applied.
374    * @param implementationContext The implementation context to which this entry should be applied.
375    * @param annotationValueFilterFactory The annotation value filter factory to apply when writing annotations.
376    */
377    void applyBody(MethodVisitor methodVisitor, Implementation.Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory);
378   
379    /**
380    * The sort of an entry.
381    */
 
382    enum Sort {
383   
384    /**
385    * Describes a method that should not be implemented or retained in its original state.
386    */
387    SKIPPED(false, false),
388   
389    /**
390    * Describes a method that should be defined but is abstract or native, i.e. does not define any byte code.
391    */
392    DEFINED(true, false),
393   
394    /**
395    * Describes a method that is implemented in byte code.
396    */
397    IMPLEMENTED(true, true);
398   
399    /**
400    * Indicates if this sort defines a method, with or without byte code.
401    */
402    private final boolean define;
403   
404    /**
405    * Indicates if this sort defines byte code.
406    */
407    private final boolean implement;
408   
409    /**
410    * Creates a new sort.
411    *
412    * @param define Indicates if this sort defines a method, with or without byte code.
413    * @param implement Indicates if this sort defines byte code.
414    */
 
415  9 toggle Sort(boolean define, boolean implement) {
416  9 this.define = define;
417  9 this.implement = implement;
418    }
419   
420    /**
421    * Indicates if this sort defines a method, with or without byte code.
422    *
423    * @return {@code true} if this sort defines a method, with or without byte code.
424    */
 
425  158 toggle public boolean isDefined() {
426  158 return define;
427    }
428   
429    /**
430    * Indicates if this sort defines byte code.
431    *
432    * @return {@code true} if this sort defines byte code.
433    */
 
434  4514 toggle public boolean isImplemented() {
435  4514 return implement;
436    }
437   
 
438  0 toggle @Override
439    public String toString() {
440  0 return "TypeWriter.MethodPool.Entry.Sort." + name();
441    }
442    }
443   
444    /**
445    * A canonical implementation of a method that is not declared but inherited by the instrumented type.
446    */
 
447    enum ForNonDefinedMethod implements Record {
448   
449    /**
450    * The singleton instance.
451    */
452    INSTANCE;
453   
 
454  1155 toggle @Override
455    public void apply(ClassVisitor classVisitor, Implementation.Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory) {
456    /* do nothing */
457    }
458   
 
459  1 toggle @Override
460    public void applyBody(MethodVisitor methodVisitor, Implementation.Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory) {
461  1 throw new IllegalStateException("Cannot apply headless implementation for method that should be skipped");
462    }
463   
 
464  1 toggle @Override
465    public void applyHead(MethodVisitor methodVisitor) {
466  1 throw new IllegalStateException("Cannot apply headless implementation for method that should be skipped");
467    }
468   
 
469  1 toggle @Override
470    public MethodDescription getMethod() {
471  1 throw new IllegalStateException("A method that is not defined cannot be extracted");
472    }
473   
 
474  1331 toggle @Override
475    public Sort getSort() {
476  1331 return Sort.SKIPPED;
477    }
478   
 
479  1 toggle @Override
480    public Record prepend(ByteCodeAppender byteCodeAppender) {
481  1 throw new IllegalStateException("Cannot prepend code to non-implemented method");
482    }
483   
 
484  1 toggle @Override
485    public String toString() {
486  1 return "TypeWriter.MethodPool.Record.ForNonDefinedMethod." + name();
487    }
488    }
489   
490    /**
491    * A base implementation of an abstract entry that defines a method.
492    */
 
493    abstract class ForDefinedMethod implements Record {
494   
 
495  3065 toggle @Override
496    public void apply(ClassVisitor classVisitor, Implementation.Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory) {
497  3065 MethodVisitor methodVisitor = classVisitor.visitMethod(getMethod().getActualModifiers(getSort().isImplemented()),
498    getMethod().getInternalName(),
499    getMethod().getDescriptor(),
500    getMethod().getGenericSignature(),
501    getMethod().getExceptionTypes().asErasures().toInternalNames());
502  3050 ParameterList<?> parameterList = getMethod().getParameters();
503  3050 if (parameterList.hasExplicitMetaData()) {
504  1895 for (ParameterDescription parameterDescription : parameterList) {
505  14 methodVisitor.visitParameter(parameterDescription.getName(), parameterDescription.getModifiers());
506    }
507    }
508  3050 applyHead(methodVisitor);
509  3049 applyBody(methodVisitor, implementationContext, annotationValueFilterFactory);
510  2984 methodVisitor.visitEnd();
511    }
512   
513    /**
514    * Describes an entry that defines a method as byte code.
515    */
 
516    public static class WithBody extends ForDefinedMethod {
517   
518    /**
519    * The implemented method.
520    */
521    private final MethodDescription methodDescription;
522   
523    /**
524    * The byte code appender to apply.
525    */
526    private final ByteCodeAppender byteCodeAppender;
527   
528    /**
529    * The method attribute appender to apply.
530    */
531    private final MethodAttributeAppender methodAttributeAppender;
532   
533    /**
534    * Creates a new record for an implemented method without attributes or a modifier resolver.
535    *
536    * @param methodDescription The implemented method.
537    * @param byteCodeAppender The byte code appender to apply.
538    */
 
539  146 toggle public WithBody(MethodDescription methodDescription, ByteCodeAppender byteCodeAppender) {
540  146 this(methodDescription, byteCodeAppender, MethodAttributeAppender.NoOp.INSTANCE);
541    }
542   
543    /**
544    * Creates a new entry for a method that defines a method as byte code.
545    *
546    * @param methodDescription The implemented method.
547    * @param byteCodeAppender The byte code appender to apply.
548    * @param methodAttributeAppender The method attribute appender to apply.
549    */
 
550  2865 toggle public WithBody(MethodDescription methodDescription, ByteCodeAppender byteCodeAppender, MethodAttributeAppender methodAttributeAppender) {
551  2865 this.methodDescription = methodDescription;
552  2865 this.byteCodeAppender = byteCodeAppender;
553  2865 this.methodAttributeAppender = methodAttributeAppender;
554    }
555   
 
556  16518 toggle @Override
557    public MethodDescription getMethod() {
558  16518 return methodDescription;
559    }
560   
 
561  2973 toggle @Override
562    public Sort getSort() {
563  2973 return Sort.IMPLEMENTED;
564    }
565   
 
566  2844 toggle @Override
567    public void applyHead(MethodVisitor methodVisitor) {
568    /* do nothing */
569    }
570   
 
571  2844 toggle @Override
572    public void applyBody(MethodVisitor methodVisitor, Implementation.Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory) {
573  2844 methodAttributeAppender.apply(methodVisitor, methodDescription, annotationValueFilterFactory.on(methodDescription));
574  2843 methodVisitor.visitCode();
575  2843 ByteCodeAppender.Size size = byteCodeAppender.apply(methodVisitor, implementationContext, methodDescription);
576  2779 methodVisitor.visitMaxs(size.getOperandStackSize(), size.getLocalVariableSize());
577    }
578   
 
579  3 toggle @Override
580    public Record prepend(ByteCodeAppender byteCodeAppender) {
581  3 return new WithBody(methodDescription, new ByteCodeAppender.Compound(byteCodeAppender, this.byteCodeAppender), methodAttributeAppender);
582    }
583   
 
584  13 toggle @Override
585    public boolean equals(Object other) {
586  2 if (this == other) return true;
587  4 if (other == null || getClass() != other.getClass()) return false;
588  7 WithBody withBody = (WithBody) other;
589  7 return methodDescription.equals(withBody.methodDescription)
590    && byteCodeAppender.equals(withBody.byteCodeAppender)
591    && methodAttributeAppender.equals(withBody.methodAttributeAppender);
592    }
593   
 
594  9 toggle @Override
595    public int hashCode() {
596  9 int result = methodDescription.hashCode();
597  9 result = 31 * result + byteCodeAppender.hashCode();
598  9 result = 31 * result + methodAttributeAppender.hashCode();
599  9 return result;
600    }
601   
 
602  16 toggle @Override
603    public String toString() {
604  16 return "TypeWriter.MethodPool.Record.ForDefinedMethod.WithBody{" +
605    "methodDescription=" + methodDescription +
606    ", byteCodeAppender=" + byteCodeAppender +
607    ", methodAttributeAppender=" + methodAttributeAppender +
608    '}';
609    }
610    }
611   
612    /**
613    * Describes an entry that defines a method but without byte code and without an annotation value.
614    */
 
615    public static class WithoutBody extends ForDefinedMethod {
616   
617    /**
618    * The implemented method.
619    */
620    private final MethodDescription methodDescription;
621   
622    /**
623    * The method attribute appender to apply.
624    */
625    private final MethodAttributeAppender methodAttributeAppender;
626   
627    /**
628    * Creates a new entry for a method that is defines but does not append byte code, i.e. is native or abstract.
629    *
630    * @param methodDescription The implemented method.
631    * @param methodAttributeAppender The method attribute appender to apply.
632    */
 
633  46 toggle public WithoutBody(MethodDescription methodDescription, MethodAttributeAppender methodAttributeAppender) {
634  46 this.methodDescription = methodDescription;
635  46 this.methodAttributeAppender = methodAttributeAppender;
636    }
637   
 
638  218 toggle @Override
639    public MethodDescription getMethod() {
640  218 return methodDescription;
641    }
642   
 
643  41 toggle @Override
644    public Sort getSort() {
645  41 return Sort.DEFINED;
646    }
647   
 
648  29 toggle @Override
649    public void applyHead(MethodVisitor methodVisitor) {
650    /* do nothing */
651    }
652   
 
653  29 toggle @Override
654    public void applyBody(MethodVisitor methodVisitor, Implementation.Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory) {
655  29 methodAttributeAppender.apply(methodVisitor, methodDescription, annotationValueFilterFactory.on(methodDescription));
656    }
657   
 
658  1 toggle @Override
659    public Record prepend(ByteCodeAppender byteCodeAppender) {
660  1 throw new IllegalStateException("Cannot prepend code to abstract method");
661    }
662   
 
663  6 toggle @Override
664    public boolean equals(Object other) {
665  1 if (this == other) return true;
666  2 if (other == null || getClass() != other.getClass()) return false;
667  3 WithoutBody that = (WithoutBody) other;
668  3 return methodDescription.equals(that.methodDescription)
669    && methodAttributeAppender.equals(that.methodAttributeAppender);
670    }
671   
 
672  4 toggle @Override
673    public int hashCode() {
674  4 int result = methodDescription.hashCode();
675  4 result = 31 * result + methodAttributeAppender.hashCode();
676  4 return result;
677    }
678   
 
679  6 toggle @Override
680    public String toString() {
681  6 return "TypeWriter.MethodPool.Record.ForDefinedMethod.WithoutBody{" +
682    "methodDescription=" + methodDescription +
683    ", methodAttributeAppender=" + methodAttributeAppender +
684    '}';
685    }
686    }
687   
688    /**
689    * Describes an entry that defines a method with a default annotation value.
690    */
 
691    public static class WithAnnotationDefaultValue extends ForDefinedMethod {
692   
693    /**
694    * The implemented method.
695    */
696    private final MethodDescription methodDescription;
697   
698    /**
699    * The annotation value to define.
700    */
701    private final Object annotationValue;
702   
703    /**
704    * The method attribute appender to apply.
705    */
706    private final MethodAttributeAppender methodAttributeAppender;
707   
708    /**
709    * Creates a new entry for defining a method with a default annotation value.
710    *
711    * @param methodDescription The implemented method.
712    * @param annotationValue The annotation value to define.
713    * @param methodAttributeAppender The method attribute appender to apply.
714    */
 
715  18 toggle public WithAnnotationDefaultValue(MethodDescription methodDescription,
716    Object annotationValue,
717    MethodAttributeAppender methodAttributeAppender) {
718  18 this.methodDescription = methodDescription;
719  18 this.annotationValue = annotationValue;
720  18 this.methodAttributeAppender = methodAttributeAppender;
721    }
722   
 
723  42 toggle @Override
724    public MethodDescription getMethod() {
725  42 return methodDescription;
726    }
727   
 
728  14 toggle @Override
729    public Sort getSort() {
730  14 return Sort.DEFINED;
731    }
732   
 
733  8 toggle @Override
734    public void applyHead(MethodVisitor methodVisitor) {
735  8 if (!methodDescription.isDefaultValue(annotationValue)) {
736  1 throw new IllegalStateException("Cannot set " + annotationValue + " as default for " + methodDescription);
737    }
738  7 AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotationDefault();
739  7 AnnotationAppender.Default.apply(annotationVisitor,
740    methodDescription.getReturnType().asErasure(),
741    AnnotationAppender.NO_NAME,
742    annotationValue);
743  7 annotationVisitor.visitEnd();
744    }
745   
 
746  7 toggle @Override
747    public void applyBody(MethodVisitor methodVisitor, Implementation.Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory) {
748  7 methodAttributeAppender.apply(methodVisitor, methodDescription, annotationValueFilterFactory.on(methodDescription));
749    }
750   
 
751  1 toggle @Override
752    public Record prepend(ByteCodeAppender byteCodeAppender) {
753  1 throw new IllegalStateException("Cannot prepend code to method that defines a default annotation value");
754    }
755   
 
756  7 toggle @Override
757    public boolean equals(Object other) {
758  1 if (this == other) return true;
759  2 if (other == null || getClass() != other.getClass()) return false;
760  4 WithAnnotationDefaultValue that = (WithAnnotationDefaultValue) other;
761  4 return methodDescription.equals(that.methodDescription)
762    && annotationValue.equals(that.annotationValue)
763    && methodAttributeAppender.equals(that.methodAttributeAppender);
764    }
765   
 
766  5 toggle @Override
767    public int hashCode() {
768  5 int result = methodDescription.hashCode();
769  5 result = 31 * result + annotationValue.hashCode();
770  5 result = 31 * result + methodAttributeAppender.hashCode();
771  5 return result;
772    }
773   
 
774  8 toggle @Override
775    public String toString() {
776  8 return "TypeWriter.MethodPool.Record.ForDefinedMethod.WithAnnotationDefaultValue{" +
777    "methodDescription=" + methodDescription +
778    ", annotationValue=" + annotationValue +
779    ", methodAttributeAppender=" + methodAttributeAppender +
780    '}';
781    }
782    }
783   
784    /**
785    * A record for a visibility bridge.
786    */
 
787    public static class OfVisibilityBridge extends ForDefinedMethod implements ByteCodeAppender {
788   
789    /**
790    * The visibility bridge.
791    */
792    private final MethodDescription visibilityBridge;
793   
794    /**
795    * The method the visibility bridge invokes.
796    */
797    private final MethodDescription bridgeTarget;
798   
799    /**
800    * The super type of the instrumented type.
801    */
802    private final TypeDescription superClass;
803   
804    /**
805    * The attribute appender to apply to the visibility bridge.
806    */
807    private final MethodAttributeAppender attributeAppender;
808   
809    /**
810    * Creates a new record for a visibility bridge.
811    *
812    * @param visibilityBridge The visibility bridge.
813    * @param bridgeTarget The method the visibility bridge invokes.
814    * @param superClass The super type of the instrumented type.
815    * @param attributeAppender The attribute appender to apply to the visibility bridge.
816    */
 
817  15 toggle protected OfVisibilityBridge(MethodDescription visibilityBridge,
818    MethodDescription bridgeTarget,
819    TypeDescription superClass,
820    MethodAttributeAppender attributeAppender) {
821  15 this.visibilityBridge = visibilityBridge;
822  15 this.bridgeTarget = bridgeTarget;
823  15 this.superClass = superClass;
824  15 this.attributeAppender = attributeAppender;
825    }
826   
827    /**
828    * Creates a record for a visibility bridge.
829    *
830    * @param instrumentedType The instrumented type.
831    * @param bridgeTarget The target method of the visibility bridge.
832    * @param attributeAppender The attribute appender to apply to the visibility bridge.
833    * @return A record describing the visibility bridge.
834    */
 
835  7 toggle public static Record of(TypeDescription instrumentedType, MethodDescription bridgeTarget, MethodAttributeAppender attributeAppender) {
836  7 return new OfVisibilityBridge(new VisibilityBridge(instrumentedType, bridgeTarget),
837    bridgeTarget,
838    instrumentedType.getSuperClass().asErasure(),
839    attributeAppender);
840    }
841   
 
842  36 toggle @Override
843    public MethodDescription getMethod() {
844  36 return visibilityBridge;
845    }
846   
 
847  7 toggle @Override
848    public Sort getSort() {
849  7 return Sort.IMPLEMENTED;
850    }
851   
 
852  1 toggle @Override
853    public Record prepend(ByteCodeAppender byteCodeAppender) {
854  1 return new ForDefinedMethod.WithBody(visibilityBridge, new ByteCodeAppender.Compound(this, byteCodeAppender), attributeAppender);
855    }
856   
 
857  6 toggle @Override
858    public void applyHead(MethodVisitor methodVisitor) {
859    /* do nothing */
860    }
861   
 
862  6 toggle @Override
863    public void applyBody(MethodVisitor methodVisitor, Implementation.Context implementationContext, AnnotationValueFilter.Factory annotationValueFilterFactory) {
864  6 attributeAppender.apply(methodVisitor, visibilityBridge, annotationValueFilterFactory.on(visibilityBridge));
865  6 methodVisitor.visitCode();
866  6 ByteCodeAppender.Size size = apply(methodVisitor, implementationContext, visibilityBridge);
867  6 methodVisitor.visitMaxs(size.getOperandStackSize(), size.getLocalVariableSize());
868    }
869   
 
870  6 toggle @Override
871    public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) {
872  6 return new ByteCodeAppender.Simple(
873    MethodVariableAccess.allArgumentsOf(instrumentedMethod).prependThisReference(),
874    MethodInvocation.invoke(bridgeTarget).special(superClass),
875    MethodReturn.returning(instrumentedMethod.getReturnType().asErasure())
876    ).apply(methodVisitor, implementationContext, instrumentedMethod);
877    }
878   
 
879  8 toggle @Override
880    public boolean equals(Object other) {
881  1 if (this == other) return true;
882  2 if (other == null || getClass() != other.getClass()) return false;
883  5 OfVisibilityBridge that = (OfVisibilityBridge) other;
884  5 return visibilityBridge.equals(that.visibilityBridge)
885    && bridgeTarget.equals(that.bridgeTarget)
886    && superClass.equals(that.superClass)
887    && attributeAppender.equals(that.attributeAppender);
888    }
889   
 
890  6 toggle @Override
891    public int hashCode() {
892  6 int result = visibilityBridge.hashCode();
893  6 result = 31 * result + bridgeTarget.hashCode();
894  6 result = 31 * result + superClass.hashCode();
895  6 result = 31 * result + attributeAppender.hashCode();
896  6 return result;
897    }
898   
 
899  10 toggle @Override
900    public String toString() {
901  10 return "TypeWriter.MethodPool.Record.ForDefinedMethod.OfVisibilityBridge{" +
902    "visibilityBridge=" + visibilityBridge +
903    ", bridgeTarget=" + bridgeTarget +
904    ", superClass=" + superClass +
905    ", attributeAppender=" + attributeAppender +
906    '}';
907    }
908   
909    /**
910    * A method describing a visibility bridge.
911    */
 
912    protected static class VisibilityBridge extends MethodDescription.InDefinedShape.AbstractBase {
913   
914    /**
915    * The instrumented type.
916    */
917    private final TypeDescription instrumentedType;
918   
919    /**
920    * The method that is the target of the bridge.
921    */
922    private final MethodDescription bridgeTarget;
923   
924    /**
925    * Creates a new visibility bridge.
926    *
927    * @param instrumentedType The instrumented type.
928    * @param bridgeTarget The method that is the target of the bridge.
929    */
 
930  7 toggle protected VisibilityBridge(TypeDescription instrumentedType, MethodDescription bridgeTarget) {
931  7 this.instrumentedType = instrumentedType;
932  7 this.bridgeTarget = bridgeTarget;
933    }
934   
 
935  24 toggle @Override
936    public TypeDescription getDeclaringType() {
937  24 return instrumentedType;
938    }
939   
 
940  36 toggle @Override
941    public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
942  36 return new ParameterList.Explicit.ForTypes(this, bridgeTarget.getParameters().asTypeList().asRawTypes());
943    }
944   
 
945  18 toggle @Override
946    public TypeDescription.Generic getReturnType() {
947  18 return bridgeTarget.getReturnType().asRawType();
948    }
949   
 
950  12 toggle @Override
951    public TypeList.Generic getExceptionTypes() {
952  12 return bridgeTarget.getExceptionTypes().asRawTypes();
953    }
954   
 
955  0 toggle @Override
956    public Object getDefaultValue() {
957  0 return MethodDescription.NO_DEFAULT_VALUE;
958    }
959   
 
960  6 toggle @Override
961    public TypeList.Generic getTypeVariables() {
962  6 return new TypeList.Generic.Empty();
963    }
964   
 
965  6 toggle @Override
966    public AnnotationList getDeclaredAnnotations() {
967  6 return bridgeTarget.getDeclaredAnnotations();
968    }
969   
 
970  48 toggle @Override
971    public int getModifiers() {
972  48 return (bridgeTarget.getModifiers() | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE) & ~Opcodes.ACC_NATIVE;
973    }
974   
 
975  6 toggle @Override
976    public String getInternalName() {
977  6 return bridgeTarget.getName();
978    }
979    }
980    }
981    }
982   
983    /**
984    * A wrapper that appends accessor bridges for a method's implementation. The bridges are only added if
985    * {@link net.bytebuddy.dynamic.scaffold.TypeWriter.MethodPool.Record#apply(ClassVisitor, Implementation.Context, AnnotationValueFilter.Factory)}
986    * is invoked such that bridges are not appended for methods that are rebased or redefined as such types already have bridge methods in place.
987    */
 
988    class AccessBridgeWrapper implements Record {
989   
990    /**
991    * The delegate for implementing the bridge's target.
992    */
993    private final Record delegate;
994   
995    /**
996    * The instrumented type that defines the bridge methods and the bridge target.
997    */
998    private final TypeDescription instrumentedType;
999   
1000    /**
1001    * The target of the bridge method.
1002    */
1003    private final MethodDescription bridgeTarget;
1004   
1005    /**
1006    * A collection of all tokens representing all bridge methods.
1007    */
1008    private final Set<MethodDescription.TypeToken> bridgeTypes;
1009   
1010    /**
1011    * The attribute appender being applied for the bridge target.
1012    */
1013    private final MethodAttributeAppender attributeAppender;
1014   
1015    /**
1016    * Creates a wrapper for adding accessor bridges.
1017    *
1018    * @param delegate The delegate for implementing the bridge's target.
1019    * @param instrumentedType The instrumented type that defines the bridge methods and the bridge target.
1020    * @param bridgeTarget The target of the bridge method.
1021    * @param bridgeTypes A collection of all tokens representing all bridge methods.
1022    * @param attributeAppender The attribute appender being applied for the bridge target.
1023    */
 
1024  26 toggle protected AccessBridgeWrapper(Record delegate,
1025    TypeDescription instrumentedType,
1026    MethodDescription bridgeTarget,
1027    Set<MethodDescription.TypeToken> bridgeTypes,
1028    MethodAttributeAppender attributeAppender) {
1029  26 this.delegate = delegate;
1030  26 this.instrumentedType = instrumentedType;
1031  26 this.bridgeTarget = bridgeTarget;
1032  26 this.bridgeTypes = bridgeTypes;
1033  26 this.attributeAppender = attributeAppender;
1034    }
1035   
1036    /**
1037    * Wraps the given record in an accessor bridge wrapper if necessary.
1038    *
1039    * @param delegate The delegate for implementing the bridge's target.
1040    * @param instrumentedType The instrumented type that defines the bridge methods and the bridge target.
1041    * @param bridgeTarget The bridge methods' target methods.
1042    * @param bridgeTypes A collection of all tokens representing all bridge methods.
1043    * @param attributeAppender The attribute appender being applied for the bridge target.
1044    * @return The given record wrapped by a bridge method wrapper if necessary.
1045    */
 
1046  2756 toggle public static Record of(Record delegate,
1047    TypeDescription instrumentedType,
1048    MethodDescription bridgeTarget,
1049    Set<MethodDescription.TypeToken> bridgeTypes,
1050    MethodAttributeAppender attributeAppender) {
1051  2756 return bridgeTypes.isEmpty() || (instrumentedType.isInterface() && !delegate.getSort().isImplemented())
1052    ? delegate
1053    : new AccessBridgeWrapper(delegate, instrumentedType, bridgeTarget, bridgeTypes, attributeAppender);
1054    }
1055   
 
1056  1 toggle @Override
1057    public Sort getSort() {
1058  1 return delegate.getSort();
1059    }
1060   
 
1061  0 toggle @Override
1062    public MethodDescription getMethod() {
1063  0 return bridgeTarget;
1064    }
1065   
 
1066  1 toggle @Override
1067    public Record prepend(ByteCodeAppender byteCodeAppender) {
1068  1 return new AccessBridgeWrapper(delegate.prepend(byteCodeAppender), instrumentedType, bridgeTarget, bridgeTypes, attributeAppender);
1069    }
1070   
 
1071  14 toggle @Override
1072    public void apply(ClassVisitor classVisitor,
1073    Implementation.Context implementationContext,
1074    AnnotationValueFilter.Factory annotationValueFilterFactory) {
1075  14 delegate.apply(classVisitor, implementationContext, annotationValueFilterFactory);
1076  14 for (MethodDescription.TypeToken bridgeType : bridgeTypes) {
1077  14 MethodDescription.InDefinedShape bridgeMethod = new AccessorBridge(bridgeTarget, bridgeType, instrumentedType);
1078  14 MethodDescription.InDefinedShape bridgeTarget = new BridgeTarget(this.bridgeTarget, instrumentedType);
1079  14 MethodVisitor methodVisitor = classVisitor.visitMethod(bridgeMethod.getActualModifiers(true),
1080    bridgeMethod.getInternalName(),
1081    bridgeMethod.getDescriptor(),
1082    MethodDescription.NON_GENERIC_SIGNATURE,
1083    bridgeMethod.getExceptionTypes().asErasures().toInternalNames());
1084  14 attributeAppender.apply(methodVisitor, bridgeMethod, annotationValueFilterFactory.on(instrumentedType));
1085  14 methodVisitor.visitCode();
1086  14 ByteCodeAppender.Size size = new ByteCodeAppender.Simple(
1087    MethodVariableAccess.allArgumentsOf(bridgeMethod).asBridgeOf(bridgeTarget).prependThisReference(),
1088    MethodInvocation.invoke(bridgeTarget).virtual(instrumentedType),
1089  14 bridgeTarget.getReturnType().asErasure().isAssignableTo(bridgeMethod.getReturnType().asErasure())
1090    ? StackManipulation.Trivial.INSTANCE
1091    : TypeCasting.to(bridgeMethod.getReturnType().asErasure()),
1092    MethodReturn.returning(bridgeMethod.getReturnType().asErasure())
1093    ).apply(methodVisitor, implementationContext, bridgeMethod);
1094  14 methodVisitor.visitMaxs(size.getOperandStackSize(), size.getLocalVariableSize());
1095  14 methodVisitor.visitEnd();
1096    }
1097    }
1098   
 
1099  1 toggle @Override
1100    public void applyHead(MethodVisitor methodVisitor) {
1101  1 delegate.applyHead(methodVisitor);
1102    }
1103   
 
1104  1 toggle @Override
1105    public void applyBody(MethodVisitor methodVisitor,
1106    Implementation.Context implementationContext,
1107    AnnotationValueFilter.Factory annotationValueFilterFactory) {
1108  1 delegate.applyBody(methodVisitor, implementationContext, annotationValueFilterFactory);
1109    }
1110   
 
1111  9 toggle @Override
1112    public boolean equals(Object other) {
1113  1 if (this == other) return true;
1114  2 if (other == null || getClass() != other.getClass()) return false;
1115  6 AccessBridgeWrapper that = (AccessBridgeWrapper) other;
1116  6 return delegate.equals(that.delegate)
1117    && instrumentedType.equals(that.instrumentedType)
1118    && bridgeTarget.equals(that.bridgeTarget)
1119    && bridgeTypes.equals(that.bridgeTypes)
1120    && attributeAppender.equals(that.attributeAppender);
1121    }
1122   
 
1123  7 toggle @Override
1124    public int hashCode() {
1125  7 int result = delegate.hashCode();
1126  7 result = 31 * result + instrumentedType.hashCode();
1127  7 result = 31 * result + bridgeTarget.hashCode();
1128  7 result = 31 * result + bridgeTypes.hashCode();
1129  7 result = 31 * result + attributeAppender.hashCode();
1130  7 return result;
1131    }
1132   
 
1133  7 toggle @Override
1134    public String toString() {
1135  7 return "TypeWriter.MethodPool.Record.AccessBridgeWrapper{" +
1136    "delegate=" + delegate +
1137    ", instrumentedType=" + instrumentedType +
1138    ", bridgeTarget=" + bridgeTarget +
1139    ", bridgeTypes=" + bridgeTypes +
1140    ", attributeAppender=" + attributeAppender +
1141    '}';
1142    }
1143   
1144    /**
1145    * A method representing an accessor bridge method.
1146    */
 
1147    protected static class AccessorBridge extends MethodDescription.InDefinedShape.AbstractBase {
1148   
1149    /**
1150    * The target method of the bridge.
1151    */
1152    private final MethodDescription bridgeTarget;
1153   
1154    /**
1155    * The bridge's type token.
1156    */
1157    private final MethodDescription.TypeToken bridgeType;
1158   
1159    /**
1160    * The instrumented type defining the bridge target.
1161    */
1162    private final TypeDescription instrumentedType;
1163   
1164    /**
1165    * Creates a new accessor bridge method.
1166    *
1167    * @param bridgeTarget The target method of the bridge.
1168    * @param bridgeType The bridge's type token.
1169    * @param instrumentedType The instrumented type defining the bridge target.
1170    */
 
1171  14 toggle protected AccessorBridge(MethodDescription bridgeTarget, TypeToken bridgeType, TypeDescription instrumentedType) {
1172  14 this.bridgeTarget = bridgeTarget;
1173  14 this.bridgeType = bridgeType;
1174  14 this.instrumentedType = instrumentedType;
1175    }
1176   
 
1177  24 toggle @Override
1178    public TypeDescription getDeclaringType() {
1179  24 return instrumentedType;
1180    }
1181   
 
1182  45 toggle @Override
1183    public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1184  45 return new ParameterList.Explicit.ForTypes(this, bridgeType.getParameterTypes());
1185    }
1186   
 
1187  48 toggle @Override
1188    public TypeDescription.Generic getReturnType() {
1189  48 return bridgeType.getReturnType().asGenericType();
1190    }
1191   
 
1192  17 toggle @Override
1193    public TypeList.Generic getExceptionTypes() {
1194  17 return bridgeTarget.getExceptionTypes().accept(TypeDescription.Generic.Visitor.TypeErasing.INSTANCE);
1195    }
1196   
 
1197  0 toggle @Override
1198    public Object getDefaultValue() {
1199  0 return MethodDescription.NO_DEFAULT_VALUE;
1200    }
1201   
 
1202  3 toggle @Override
1203    public TypeList.Generic getTypeVariables() {
1204  3 return new TypeList.Generic.Empty();
1205    }
1206   
 
1207  17 toggle @Override
1208    public AnnotationList getDeclaredAnnotations() {
1209  17 return new AnnotationList.Empty();
1210    }
1211   
 
1212  66 toggle @Override
1213    public int getModifiers() {
1214  66 return (bridgeTarget.getModifiers() | Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC) & ~(Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE);
1215    }
1216   
 
1217  17 toggle @Override
1218    public String getInternalName() {
1219  17 return bridgeTarget.getInternalName();
1220    }
1221    }
1222   
1223    /**
1224    * A method representing a bridge's target method in its defined shape.
1225    */
 
1226    protected static class BridgeTarget extends MethodDescription.InDefinedShape.AbstractBase {
1227   
1228    /**
1229    * The target method of the bridge.
1230    */
1231    private final MethodDescription bridgeTarget;
1232   
1233    /**
1234    * The instrumented type defining the bridge target.
1235    */
1236    private final TypeDescription instrumentedType;
1237   
1238    /**
1239    * Creates a new bridge target.
1240    *
1241    * @param bridgeTarget The target method of the bridge.
1242    * @param instrumentedType The instrumented type defining the bridge target.
1243    */
 
1244  14 toggle protected BridgeTarget(MethodDescription bridgeTarget, TypeDescription instrumentedType) {
1245  14 this.bridgeTarget = bridgeTarget;
1246  14 this.instrumentedType = instrumentedType;
1247    }
1248   
 
1249  49 toggle @Override
1250    public TypeDescription getDeclaringType() {
1251  49 return instrumentedType;
1252    }
1253   
 
1254  35 toggle @Override
1255    public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
1256  35 return new ParameterList.ForTokens(this, bridgeTarget.getParameters().asTokenList(is(instrumentedType)));
1257    }
1258   
 
1259  42 toggle @Override
1260    public TypeDescription.Generic getReturnType() {
1261  42 return bridgeTarget.getReturnType();
1262    }
1263   
 
1264  0 toggle @Override
1265    public TypeList.Generic getExceptionTypes() {
1266  0 return bridgeTarget.getExceptionTypes();
1267    }
1268   
 
1269  0 toggle @Override
1270    public Object getDefaultValue() {
1271  0 return bridgeTarget.getDefaultValue();
1272    }
1273   
 
1274  0 toggle @Override
1275    public TypeList.Generic getTypeVariables() {
1276  0 return bridgeTarget.getTypeVariables();
1277    }
1278   
 
1279  0 toggle @Override
1280    public AnnotationList getDeclaredAnnotations() {
1281  0 return bridgeTarget.getDeclaredAnnotations();
1282    }
1283   
 
1284  91 toggle @Override
1285    public int getModifiers() {
1286  91 return bridgeTarget.getModifiers();
1287    }
1288   
 
1289  56 toggle @Override
1290    public String getInternalName() {
1291  56 return bridgeTarget.getInternalName();
1292    }
1293    }
1294    }
1295    }
1296    }
1297   
1298    /**
1299    * A default implementation of a {@link net.bytebuddy.dynamic.scaffold.TypeWriter}.
1300    *
1301    * @param <S> The best known loaded type for the dynamically created type.
1302    */
 
1303    abstract class Default<S> implements TypeWriter<S> {
1304   
1305    /**
1306    * A folder for dumping class files or {@code null} if no dump should be generated.
1307    */
1308    private static final String DUMP_FOLDER;
1309   
1310    /*
1311    * Reads the dumping property that is set at program start up. This might cause an error because of security constraints.
1312    */
 
1313  3 toggle static {
1314  3 String dumpFolder;
1315  3 try {
1316  3 dumpFolder = System.getProperty(DUMP_PROPERTY);
1317    } catch (RuntimeException exception) {
1318  0 dumpFolder = null;
1319  0 Logger.getLogger("net.bytebuddy").warning("Could not enable dumping of class files: " + exception.getMessage());
1320    }
1321  3 DUMP_FOLDER = dumpFolder;
1322    }
1323   
1324    /**
1325    * The instrumented type to be created.
1326    */
1327    protected final TypeDescription instrumentedType;
1328   
1329    /**
1330    * The field pool to use.
1331    */
1332    protected final FieldPool fieldPool;
1333   
1334    /**
1335    * The method pool to use.
1336    */
1337    protected final MethodPool methodPool;
1338   
1339    /**
1340    * The explicit auxiliary types to add to the created type.
1341    */
1342    protected final List<DynamicType> explicitAuxiliaryTypes;
1343   
1344    /**
1345    * The instrumented methods relevant to this type creation.
1346    */
1347    protected final MethodList<?> instrumentedMethods;
1348   
1349    /**
1350    * The loaded type initializer to apply onto the created type after loading.
1351    */
1352    protected final LoadedTypeInitializer loadedTypeInitializer;
1353   
1354    /**
1355    * The type initializer to include in the created type's type initializer.
1356    */
1357    protected final TypeInitializer typeInitializer;
1358   
1359    /**
1360    * The type attribute appender to apply onto the instrumented type.
1361    */
1362    protected final TypeAttributeAppender typeAttributeAppender;
1363   
1364    /**
1365    * The ASM visitor wrapper to apply onto the class writer.
1366    */
1367    protected final AsmVisitorWrapper asmVisitorWrapper;
1368   
1369    /**
1370    * The class file version to use when no explicit class file version is applied.
1371    */
1372    protected final ClassFileVersion classFileVersion;
1373   
1374    /**
1375    * The annotation value filter factory to apply.
1376    */
1377    protected final AnnotationValueFilter.Factory annotationValueFilterFactory;
1378   
1379    /**
1380    * The annotation retention to apply.
1381    */
1382    protected final AnnotationRetention annotationRetention;
1383   
1384    /**
1385    * The naming strategy for auxiliary types to apply.
1386    */
1387    protected final AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy;
1388   
1389    /**
1390    * The implementation context factory to apply.
1391    */
1392    protected final Implementation.Context.Factory implementationContextFactory;
1393   
1394    /**
1395    * Determines if a type should be explicitly validated.
1396    */
1397    protected final TypeValidation typeValidation;
1398   
1399    /**
1400    * The type pool to use for computing stack map frames, if required.
1401    */
1402    protected final TypePool typePool;
1403   
1404    /**
1405    * Creates a new default type writer.
1406    *
1407    * @param instrumentedType The instrumented type to be created.
1408    * @param fieldPool The field pool to use.
1409    * @param methodPool The method pool to use.
1410    * @param explicitAuxiliaryTypes The explicit auxiliary types to add to the created type.
1411    * @param instrumentedMethods The instrumented methods relevant to this type creation.
1412    * @param loadedTypeInitializer The loaded type initializer to apply onto the created type after loading.
1413    * @param typeInitializer The type initializer to include in the created type's type initializer.
1414    * @param typeAttributeAppender The type attribute appender to apply onto the instrumented type.
1415    * @param asmVisitorWrapper The ASM visitor wrapper to apply onto the class writer.
1416    * @param classFileVersion The class file version to use when no explicit class file version is applied.
1417    * @param annotationValueFilterFactory The annotation value filter factory to apply.
1418    * @param annotationRetention The annotation retention to apply.
1419    * @param auxiliaryTypeNamingStrategy The naming strategy for auxiliary types to apply.
1420    * @param implementationContextFactory The implementation context factory to apply.
1421    * @param typeValidation Determines if a type should be explicitly validated.
1422    * @param typePool The type pool to use for computing stack map frames, if required.
1423    */
 
1424  1503 toggle protected Default(TypeDescription instrumentedType,
1425    FieldPool fieldPool,
1426    MethodPool methodPool,
1427    List<DynamicType> explicitAuxiliaryTypes,
1428    MethodList<?> instrumentedMethods,
1429    LoadedTypeInitializer loadedTypeInitializer,
1430    TypeInitializer typeInitializer,
1431    TypeAttributeAppender typeAttributeAppender,
1432    AsmVisitorWrapper asmVisitorWrapper,
1433    ClassFileVersion classFileVersion,
1434    AnnotationValueFilter.Factory annotationValueFilterFactory,
1435    AnnotationRetention annotationRetention,
1436    AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
1437    Implementation.Context.Factory implementationContextFactory,
1438    TypeValidation typeValidation,
1439    TypePool typePool) {
1440  1503 this.instrumentedType = instrumentedType;
1441  1503 this.fieldPool = fieldPool;
1442  1503 this.methodPool = methodPool;
1443  1503 this.explicitAuxiliaryTypes = explicitAuxiliaryTypes;
1444  1503 this.instrumentedMethods = instrumentedMethods;
1445  1503 this.loadedTypeInitializer = loadedTypeInitializer;
1446  1503 this.typeInitializer = typeInitializer;
1447  1503 this.typeAttributeAppender = typeAttributeAppender;
1448  1503 this.asmVisitorWrapper = asmVisitorWrapper;
1449  1503 this.classFileVersion = classFileVersion;
1450  1503 this.auxiliaryTypeNamingStrategy = auxiliaryTypeNamingStrategy;
1451  1503 this.annotationValueFilterFactory = annotationValueFilterFactory;
1452  1503 this.annotationRetention = annotationRetention;
1453  1503 this.implementationContextFactory = implementationContextFactory;
1454  1503 this.typeValidation = typeValidation;
1455  1503 this.typePool = typePool;
1456    }
1457   
1458    /**
1459    * Creates a type writer for creating a new type.
1460    *
1461    * @param methodRegistry The compiled method registry to use.
1462    * @param fieldPool The field pool to use.
1463    * @param typeAttributeAppender The type attribute appender to apply onto the instrumented type.
1464    * @param asmVisitorWrapper The ASM visitor wrapper to apply onto the class writer.
1465    * @param classFileVersion The class file version to use when no explicit class file version is applied.
1466    * @param annotationValueFilterFactory The annotation value filter factory to apply.
1467    * @param annotationRetention The annotation retention to apply.
1468    * @param auxiliaryTypeNamingStrategy The naming strategy for auxiliary types to apply.
1469    * @param implementationContextFactory The implementation context factory to apply.
1470    * @param typeValidation Determines if a type should be explicitly validated.
1471    * @param typePool The type pool to use for computing stack map frames, if required.
1472    * @param <U> A loaded type that the instrumented type guarantees to subclass.
1473    * @return A suitable type writer.
1474    */
 
1475  899 toggle public static <U> TypeWriter<U> forCreation(MethodRegistry.Compiled methodRegistry,
1476    FieldPool fieldPool,
1477    TypeAttributeAppender typeAttributeAppender,
1478    AsmVisitorWrapper asmVisitorWrapper,
1479    ClassFileVersion classFileVersion,
1480    AnnotationValueFilter.Factory annotationValueFilterFactory,
1481    AnnotationRetention annotationRetention,
1482    AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
1483    Implementation.Context.Factory implementationContextFactory,
1484    TypeValidation typeValidation,
1485    TypePool typePool) {
1486  899 return new ForCreation<U>(methodRegistry.getInstrumentedType(),
1487    fieldPool,
1488    methodRegistry,
1489    Collections.<DynamicType>emptyList(),
1490    methodRegistry.getInstrumentedMethods(),
1491    methodRegistry.getLoadedTypeInitializer(),
1492    methodRegistry.getTypeInitializer(),
1493    typeAttributeAppender,
1494    asmVisitorWrapper,
1495    classFileVersion,
1496    annotationValueFilterFactory,
1497    annotationRetention,
1498    auxiliaryTypeNamingStrategy,
1499    implementationContextFactory,
1500    typeValidation,
1501    typePool);
1502    }
1503   
1504    /**
1505    * Creates a type writer for redefining a type.
1506    *
1507    * @param methodRegistry The compiled method registry to use.
1508    * @param fieldPool The field pool to use.
1509    * @param typeAttributeAppender The type attribute appender to apply onto the instrumented type.
1510    * @param asmVisitorWrapper The ASM visitor wrapper to apply onto the class writer.
1511    * @param classFileVersion The class file version to use when no explicit class file version is applied.
1512    * @param annotationValueFilterFactory The annotation value filter factory to apply.
1513    * @param annotationRetention The annotation retention to apply.
1514    * @param auxiliaryTypeNamingStrategy The naming strategy for auxiliary types to apply.
1515    * @param implementationContextFactory The implementation context factory to apply.
1516    * @param typeValidation Determines if a type should be explicitly validated.
1517    * @param typePool The type pool to use for computing stack map frames, if required.
1518    * @param originalType The original type that is being redefined or rebased.
1519    * @param classFileLocator The class file locator for locating the original type's class file.
1520    * @param <U> A loaded type that the instrumented type guarantees to subclass.
1521    * @return A suitable type writer.
1522    */
 
1523  423 toggle public static <U> TypeWriter<U> forRedefinition(MethodRegistry.Compiled methodRegistry,
1524    FieldPool fieldPool,
1525    TypeAttributeAppender typeAttributeAppender,
1526    AsmVisitorWrapper asmVisitorWrapper,
1527    ClassFileVersion classFileVersion,
1528    AnnotationValueFilter.Factory annotationValueFilterFactory,
1529    AnnotationRetention annotationRetention,
1530    AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
1531    Implementation.Context.Factory implementationContextFactory,
1532    TypeValidation typeValidation,
1533    TypePool typePool,
1534    TypeDescription originalType,
1535    ClassFileLocator classFileLocator) {
1536  423 return new ForInlining<U>(methodRegistry.getInstrumentedType(),
1537    fieldPool,
1538    methodRegistry,
1539    Collections.<DynamicType>emptyList(),
1540    methodRegistry.getInstrumentedMethods(),
1541    methodRegistry.getLoadedTypeInitializer(),
1542    methodRegistry.getTypeInitializer(),
1543    typeAttributeAppender,
1544    asmVisitorWrapper,
1545    classFileVersion,
1546    annotationValueFilterFactory,
1547    annotationRetention,
1548    auxiliaryTypeNamingStrategy,
1549    implementationContextFactory,
1550    typeValidation,
1551    typePool,
1552    originalType,
1553    classFileLocator,
1554    MethodRebaseResolver.Disabled.INSTANCE);
1555    }
1556   
1557    /**
1558    * Creates a type writer for rebasing a type.
1559    *
1560    * @param methodRegistry The compiled method registry to use.
1561    * @param fieldPool The field pool to use.
1562    * @param typeAttributeAppender The type attribute appender to apply onto the instrumented type.
1563    * @param asmVisitorWrapper The ASM visitor wrapper to apply onto the class writer.
1564    * @param classFileVersion The class file version to use when no explicit class file version is applied.
1565    * @param annotationValueFilterFactory The annotation value filter factory to apply.
1566    * @param annotationRetention The annotation retention to apply.
1567    * @param auxiliaryTypeNamingStrategy The naming strategy for auxiliary types to apply.
1568    * @param implementationContextFactory The implementation context factory to apply.
1569    * @param typeValidation Determines if a type should be explicitly validated.
1570    * @param typePool The type pool to use for computing stack map frames, if required.
1571    * @param originalType The original type that is being redefined or rebased.
1572    * @param classFileLocator The class file locator for locating the original type's class file.
1573    * @param methodRebaseResolver The method rebase resolver to use for rebasing names.
1574    * @param <U> A loaded type that the instrumented type guarantees to subclass.
1575    * @return A suitable type writer.
1576    */
 
1577  142 toggle public static <U> TypeWriter<U> forRebasing(MethodRegistry.Compiled methodRegistry,
1578    FieldPool fieldPool,
1579    TypeAttributeAppender typeAttributeAppender,
1580    AsmVisitorWrapper asmVisitorWrapper,
1581    ClassFileVersion classFileVersion,
1582    AnnotationValueFilter.Factory annotationValueFilterFactory,
1583    AnnotationRetention annotationRetention,
1584    AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
1585    Implementation.Context.Factory implementationContextFactory,
1586    TypeValidation typeValidation,
1587    TypePool typePool,
1588    TypeDescription originalType,
1589    ClassFileLocator classFileLocator,
1590    MethodRebaseResolver methodRebaseResolver) {
1591  142 return new ForInlining<U>(methodRegistry.getInstrumentedType(),
1592    fieldPool,
1593    methodRegistry,
1594    methodRebaseResolver.getAuxiliaryTypes(),
1595    methodRegistry.getInstrumentedMethods(),
1596    methodRegistry.getLoadedTypeInitializer(),
1597    methodRegistry.getTypeInitializer(),
1598    typeAttributeAppender,
1599    asmVisitorWrapper,
1600    classFileVersion,
1601    annotationValueFilterFactory,
1602    annotationRetention,
1603    auxiliaryTypeNamingStrategy,
1604    implementationContextFactory,
1605    typeValidation,
1606    typePool,
1607    originalType,
1608    classFileLocator,
1609    methodRebaseResolver);
1610    }
1611   
 
1612  1464 toggle @Override
1613    @SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "Setting a debugging property should not change program outcome")
1614    public DynamicType.Unloaded<S> make() {
1615  1464 Implementation.Context.ExtractableView implementationContext = implementationContextFactory.make(instrumentedType,
1616    auxiliaryTypeNamingStrategy,
1617    typeInitializer,
1618    classFileVersion);
1619  1464 byte[] binaryRepresentation = create(implementationContext);
1620  1334 if (DUMP_FOLDER != null) {
1621  0 try {
1622  0 OutputStream outputStream = new FileOutputStream(new File(DUMP_FOLDER, instrumentedType.getName() + "." + System.currentTimeMillis()));
1623  0 try {
1624  0 outputStream.write(binaryRepresentation);
1625    } finally {
1626  0 outputStream.close();
1627    }
1628    } catch (Exception exception) {
1629  0 Logger.getLogger("net.bytebuddy").warning("Could not dump class file for " + instrumentedType + ": " + exception.getMessage());
1630    }
1631    }
1632  1334 return new DynamicType.Default.Unloaded<S>(instrumentedType,
1633    binaryRepresentation,
1634    loadedTypeInitializer,
1635    CompoundList.of(explicitAuxiliaryTypes, implementationContext.getRegisteredAuxiliaryTypes()));
1636    }
1637   
1638    /**
1639    * Creates the instrumented type.
1640    *
1641    * @param implementationContext The implementation context to use.
1642    * @return A byte array that is represented by the instrumented type.
1643    */
1644    protected abstract byte[] create(Implementation.Context.ExtractableView implementationContext);
1645   
 
1646  40 toggle @Override
1647    public boolean equals(Object other) {
1648  1 if (this == other) return true;
1649  2 if (other == null || getClass() != other.getClass()) return false;
1650  37 Default<?> aDefault = (Default<?>) other;
1651  37 return instrumentedType.equals(aDefault.instrumentedType)
1652    && fieldPool.equals(aDefault.fieldPool)
1653    && methodPool.equals(aDefault.methodPool)
1654    && explicitAuxiliaryTypes.equals(aDefault.explicitAuxiliaryTypes)
1655    && instrumentedMethods.equals(aDefault.instrumentedMethods)
1656    && loadedTypeInitializer.equals(aDefault.loadedTypeInitializer)
1657    && typeInitializer.equals(aDefault.typeInitializer)
1658    && typeAttributeAppender.equals(aDefault.typeAttributeAppender)
1659    && asmVisitorWrapper.equals(aDefault.asmVisitorWrapper)
1660    && classFileVersion.equals(aDefault.classFileVersion)
1661    && annotationValueFilterFactory.equals(aDefault.annotationValueFilterFactory)
1662    && annotationRetention == aDefault.annotationRetention
1663    && auxiliaryTypeNamingStrategy.equals(aDefault.auxiliaryTypeNamingStrategy)
1664    && implementationContextFactory.equals(aDefault.implementationContextFactory)
1665    && typeValidation.equals(aDefault.typeValidation)
1666    && typePool.equals(aDefault.typePool);
1667    }
1668   
 
1669  39 toggle @Override
1670    public int hashCode() {
1671  39 int result = instrumentedType.hashCode();
1672  39 result = 31 * result + fieldPool.hashCode();
1673  39 result = 31 * result + methodPool.hashCode();
1674  39 result = 31 * result + explicitAuxiliaryTypes.hashCode();
1675  39 result = 31 * result + instrumentedMethods.hashCode();
1676  39 result = 31 * result + loadedTypeInitializer.hashCode();
1677  39 result = 31 * result + typeInitializer.hashCode();
1678  39 result = 31 * result + typeAttributeAppender.hashCode();
1679  39 result = 31 * result + asmVisitorWrapper.hashCode();
1680  39 result = 31 * result + classFileVersion.hashCode();
1681  39 result = 31 * result + annotationValueFilterFactory.hashCode();
1682  39 result = 31 * result + annotationRetention.hashCode();
1683  39 result = 31 * result + auxiliaryTypeNamingStrategy.hashCode();
1684  39 result = 31 * result + implementationContextFactory.hashCode();
1685  39 result = 31 * result + typeValidation.hashCode();
1686  39 result = 31 * result + typePool.hashCode();
1687  39 return result;
1688    }
1689   
1690    /**
1691    * A class validator that validates that a class only defines members that are appropriate for the sort of the generated class.
1692    */
 
1693    protected static class ValidatingClassVisitor extends ClassVisitor {
1694   
1695    /**
1696    * Indicates that a method has no method parameters.
1697    */
1698    private static final String NO_PARAMETERS = "()";
1699   
1700    /**
1701    * Indicates that a method returns void.
1702    */
1703    private static final String RETURNS_VOID = "V";
1704   
1705    /**
1706    * The descriptor of the {@link String} type.
1707    */
1708    private static final String STRING_DESCRIPTOR = "Ljava/lang/String;";
1709   
1710    /**
1711    * The constraint to assert the members against. The constraint is first defined when the general class information is visited.
1712    */
1713    private Constraint constraint;
1714   
1715    /**
1716    * Creates a validating class visitor.
1717    *
1718    * @param classVisitor The class visitor to which any calls are delegated to.
1719    */
 
1720  1434 toggle protected ValidatingClassVisitor(ClassVisitor classVisitor) {
1721  1434 super(Opcodes.ASM5, classVisitor);
1722    }
1723   
1724    /**
1725    * Adds a validating visitor if type validation is enabled.
1726    *
1727    * @param classVisitor The original class visitor.
1728    * @param typeValidation The type validation state.
1729    * @return A class visitor that applies type validation if this is required.
1730    */
 
1731  1464 toggle protected static ClassVisitor of(ClassVisitor classVisitor, TypeValidation typeValidation) {
1732  1464 return typeValidation.isEnabled()
1733    ? new ValidatingClassVisitor(classVisitor)
1734    : classVisitor;
1735    }
1736   
 
1737  1432 toggle @Override
1738    public void visit(int version, int modifiers, String name, String signature, String superName, String[] interfaces) {
1739  1432 ClassFileVersion classFileVersion = ClassFileVersion.ofMinorMajor(version);
1740  1432 List<Constraint> constraints = new ArrayList<Constraint>();
1741  1432 constraints.add(new Constraint.ForClassFileVersion(classFileVersion));
1742  1432 if (name.endsWith('/' + PackageDescription.PACKAGE_CLASS_NAME)) {
1743  5 constraints.add(Constraint.ForPackageType.INSTANCE);
1744  1427 } else if ((modifiers & Opcodes.ACC_ANNOTATION) != 0) {
1745  13 if (!classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) {
1746  1 throw new IllegalStateException("Cannot define an annotation type for class file version " + classFileVersion);
1747    }
1748  12 constraints.add(classFileVersion.isAtLeast(ClassFileVersion.JAVA_V8)
1749    ? Constraint.ForAnnotation.JAVA_8
1750    : Constraint.ForAnnotation.CLASSIC);
1751  1414 } else if ((modifiers & Opcodes.ACC_INTERFACE) != 0) {
1752  15 constraints.add(classFileVersion.isAtLeast(ClassFileVersion.JAVA_V8)
1753    ? Constraint.ForInterface.JAVA_8
1754    : Constraint.ForInterface.CLASSIC);
1755  1399 } else if ((modifiers & Opcodes.ACC_ABSTRACT) != 0) {
1756  39 constraints.add(Constraint.ForClass.ABSTRACT);
1757    } else {
1758  1360 constraints.add(Constraint.ForClass.MANIFEST);
1759    }
1760  1431 constraint = new Constraint.Compound(constraints);
1761  1431 constraint.assertType(modifiers, interfaces != null, signature != null);
1762  1430 super.visit(version, modifiers, name, signature, superName, interfaces);
1763    }
1764   
 
1765  77 toggle @Override
1766    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
1767  77 constraint.assertAnnotation();
1768  76 return super.visitAnnotation(descriptor, visible);
1769    }
1770   
 
1771  39 toggle @Override
1772    public AnnotationVisitor visitTypeAnnotation(int typeReference, TypePath typePath, String descriptor, boolean visible) {
1773  39 constraint.assertTypeAnnotation();
1774  39 return super.visitTypeAnnotation(typeReference, typePath, descriptor, visible);
1775    }
1776   
 
1777  1801 toggle @Override
1778    public FieldVisitor visitField(int modifiers, String name, String descriptor, String signature, Object defaultValue) {
1779  1801 if (defaultValue != null) {
1780  172 Class<?> type;
1781  172 switch (descriptor.charAt(0)) {
1782  4 case 'Z':
1783  3 case 'B':
1784  3 case 'C':
1785  3 case 'S':
1786  111 case 'I':
1787  124 type = Integer.class;
1788  124 break;
1789  9 case 'J':
1790  9 type = Long.class;
1791  9 break;
1792  3 case 'F':
1793  3 type = Float.class;
1794  3 break;
1795  3 case 'D':
1796  3 type = Double.class;
1797  3 break;
1798  33 default:
1799  33 if (!descriptor.equals(STRING_DESCRIPTOR)) {
1800  1 throw new IllegalStateException("Cannot define a default value for type of field " + name);
1801    }
1802  32 type = String.class;
1803    }
1804  171 if (!type.isInstance(defaultValue)) {
1805  1 throw new IllegalStateException("Field " + name + " defines an incompatible default value " + defaultValue);
1806  170 } else if (type == Integer.class) {
1807  124 int minimum, maximum;
1808  124 switch (descriptor.charAt(0)) {
1809  4 case 'Z':
1810  4 minimum = 0;
1811  4 maximum = 1;
1812  4 break;
1813  3 case 'B':
1814  3 minimum = Byte.MIN_VALUE;
1815  3 maximum = Byte.MAX_VALUE;
1816  3 break;
1817  3 case 'C':
1818  3 minimum = Character.MIN_VALUE;
1819  3 maximum = Character.MAX_VALUE;
1820  3 break;
1821  3 case 'S':
1822  3 minimum = Short.MIN_VALUE;
1823  3 maximum = Short.MAX_VALUE;
1824  3 break;
1825  111 default:
1826  111 minimum = Integer.MIN_VALUE;
1827  111 maximum = Integer.MAX_VALUE;
1828    }
1829  124 int value = (Integer) defaultValue;
1830  124 if (value < minimum || value > maximum) {
1831  1 throw new IllegalStateException("Field " + name + " defines an incompatible default value " + defaultValue);
1832    }
1833    }
1834    }
1835  1798 constraint.assertField(name, (modifiers & Opcodes.ACC_PUBLIC) != 0, (modifiers & Opcodes.ACC_STATIC) != 0, signature != null);
1836  1793 return new ValidatingFieldVisitor(super.visitField(modifiers, name, descriptor, signature, defaultValue));
1837    }
1838   
 
1839  4359 toggle @Override
1840    public MethodVisitor visitMethod(int modifiers, String name, String descriptor, String signature, String[] exceptions) {
1841  4359 constraint.assertMethod(name,
1842    (modifiers & Opcodes.ACC_ABSTRACT) != 0,
1843    (modifiers & Opcodes.ACC_PUBLIC) != 0,
1844    (modifiers & Opcodes.ACC_STATIC) != 0,
1845    !descriptor.startsWith(NO_PARAMETERS) || descriptor.endsWith(RETURNS_VOID),
1846    name.equals(MethodDescription.CONSTRUCTOR_INTERNAL_NAME)
1847    || name.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)
1848    || (modifiers & Opcodes.ACC_PRIVATE) != 0,
1849    signature != null);
1850  4344 return new ValidatingMethodVisitor(super.visitMethod(modifiers, name, descriptor, signature, exceptions), name);
1851    }
1852   
 
1853  4 toggle @Override
1854    public String toString() {
1855  4 return "TypeWriter.Default.ValidatingClassVisitor{" +
1856    "constraint=" + constraint +
1857    "}";
1858    }
1859   
1860    /**
1861    * A constraint for members that are legal for a given type.
1862    */
 
1863    protected interface Constraint {
1864   
1865    /**
1866    * Asserts a field for being valid.
1867    *
1868    * @param name The name of the field.
1869    * @param isPublic {@code true} if this field is public.
1870    * @param isStatic {@code true} if this field is static.
1871    * @param isGeneric {@code true} if this field defines a generic signature.
1872    */
1873    void assertField(String name, boolean isPublic, boolean isStatic, boolean isGeneric);
1874   
1875    /**
1876    * Asserts a method for being valid.
1877    *
1878    * @param name The name of the method.
1879    * @param isAbstract {@code true} if the method is abstract.
1880    * @param isPublic {@code true} if this method is public.
1881    * @param isStatic {@code true} if this method is static.
1882    * @param isDefaultValueIncompatible {@code true} if a method's signature cannot describe an annotation property method.
1883    * @param isNonStaticNonVirtual {@code true} if the method is non-virtual and non-static, i.e. a constructor, type initializer or private.
1884    * @param isGeneric {@code true} if this method defines a generic signature.
1885    */
1886    void assertMethod(String name,
1887    boolean isAbstract,
1888    boolean isPublic,
1889    boolean isStatic,
1890    boolean isDefaultValueIncompatible,
1891    boolean isNonStaticNonVirtual,
1892    boolean isGeneric);
1893   
1894    /**
1895    * Asserts the legitimacy of an annotation for the instrumented type.
1896    */
1897    void assertAnnotation();
1898   
1899    /**
1900    * Asserts the legitimacy of a type annotation for the instrumented type.
1901    */
1902    void assertTypeAnnotation();
1903   
1904    /**
1905    * Asserts if a default value is legal for a method.
1906    *
1907    * @param name The name of the method.
1908    */
1909    void assertDefaultValue(String name);
1910   
1911    /**
1912    * Asserts if the type can legally represent a package description.
1913    *
1914    * @param modifier The modifier that is to be written to the type.
1915    * @param definesInterfaces {@code true} if this type implements at least one interface.
1916    * @param isGeneric {@code true} if this type defines a generic type signature.
1917    */
1918    void assertType(int modifier, boolean definesInterfaces, boolean isGeneric);
1919   
1920    /**
1921    * Asserts the capability to store a type constant in the class's constant pool.
1922    */
1923    void assertTypeInConstantPool();
1924   
1925    /**
1926    * Asserts the capability to store a method type constant in the class's constant pool.
1927    */
1928    void assertMethodTypeInConstantPool();
1929   
1930    /**
1931    * Asserts the capability to store a method handle in the class's constant pool.
1932    */
1933    void assertHandleInConstantPool();
1934   
1935    /**
1936    * Asserts the capability to invoke a method dynamically.
1937    */
1938    void assertInvokeDynamic();
1939   
1940    /**
1941    * Asserts the capability of executing a subroutine.
1942    */
1943    void assertSubRoutine();
1944   
1945    /**
1946    * Represents the constraint of a class type.
1947    */
 
1948    enum ForClass implements Constraint {
1949   
1950    /**
1951    * Represents the constraints of a non-abstract class.
1952    */
1953    MANIFEST(true),
1954   
1955    /**
1956    * Represents the constraints of an abstract class.
1957    */
1958    ABSTRACT(false);
1959   
1960    /**
1961    * {@code true} if this instance represents the constraints a non-abstract class.
1962    */
1963    private final boolean manifestType;
1964   
1965    /**
1966    * Creates a new constraint for a class.
1967    *
1968    * @param manifestType {@code true} if this instance represents a non-abstract class.
1969    */
 
1970  6 toggle ForClass(boolean manifestType) {
1971  6 this.manifestType = manifestType;
1972    }
1973   
 
1974  1790 toggle @Override
1975    public void assertField(String name, boolean isPublic, boolean isStatic, boolean isGeneric) {
1976    /* do nothing */
1977    }
1978   
 
1979  4328 toggle @Override
1980    public void assertMethod(String name,
1981    boolean isAbstract,
1982    boolean isPublic,
1983    boolean isStatic,
1984    boolean isDefaultValueIncompatible,
1985    boolean isNonStaticNonVirtual,
1986    boolean isGeneric) {
1987  4328 if (isAbstract && manifestType) {
1988  2 throw new IllegalStateException("Cannot define abstract method '" + name + "' for non-abstract class");
1989    }
1990    }
1991   
 
1992  252 toggle @Override
1993    public void assertAnnotation() {
1994    /* do nothing */
1995    }
1996   
 
1997  39 toggle @Override
1998    public void assertTypeAnnotation() {
1999    /* do nothing */
2000    }
2001   
 
2002  0 toggle @Override
2003    public void assertDefaultValue(String name) {
2004  0 throw new IllegalStateException("Cannot define default value for '" + name + "' for non-annotation type");
2005    }
2006   
 
2007  1399 toggle @Override
2008    public void assertType(int modifier, boolean definesInterfaces, boolean isGeneric) {
2009    /* do nothing */
2010    }
2011   
 
2012  813 toggle @Override
2013    public void assertTypeInConstantPool() {
2014    /* do nothing */
2015    }
2016   
 
2017  10 toggle @Override
2018    public void assertMethodTypeInConstantPool() {
2019    /* do nothing */
2020    }
2021   
 
2022  10 toggle @Override
2023    public void assertHandleInConstantPool() {
2024    /* do nothing */
2025    }
2026   
 
2027  21 toggle @Override
2028    public void assertInvokeDynamic() {
2029    /* do nothing */
2030    }
2031   
 
2032  0 toggle @Override
2033    public void assertSubRoutine() {
2034    /* do nothing */
2035    }
2036   
 
2037  2 toggle @Override
2038    public String toString() {
2039  2 return "TypeWriter.Default.ValidatingClassVisitor.Constraint.ForClass." + name();
2040    }
2041    }
2042   
2043    /**
2044    * Represents the constraint of a package type.
2045    */
 
2046    enum ForPackageType implements Constraint {
2047   
2048    /**
2049    * The singleton instance.
2050    */
2051    INSTANCE;
2052   
 
2053  1 toggle @Override
2054    public void assertField(String name, boolean isPublic, boolean isStatic, boolean isGeneric) {
2055  1 throw new IllegalStateException("Cannot define a field for a package description type");
2056    }
2057   
 
2058  1 toggle @Override
2059    public void assertMethod(String name,
2060    boolean isAbstract,
2061    boolean isPublic,
2062    boolean isStatic,
2063    boolean isDefaultValueIncompatible,
2064    boolean isNonStaticNonVirtual,
2065    boolean isGeneric) {
2066  1 throw new IllegalStateException("Cannot define a method for a package description type");
2067    }
2068   
 
2069  3 toggle @Override
2070    public void assertAnnotation() {
2071    /* do nothing */
2072    }
2073   
 
2074  0 toggle @Override
2075    public void assertTypeAnnotation() {
2076    /* do nothing */
2077    }
2078   
 
2079  0 toggle @Override
2080    public void assertDefaultValue(String name) {
2081    /* do nothing, implicit by forbidding methods */
2082    }
2083   
 
2084  0 toggle @Override
2085    public void assertTypeInConstantPool() {
2086    /* do nothing */
2087    }
2088   
 
2089  0 toggle @Override
2090    public void assertMethodTypeInConstantPool() {
2091    /* do nothing */
2092    }
2093   
 
2094  0 toggle @Override
2095    public void assertHandleInConstantPool() {
2096    /* do nothing */
2097    }
2098   
 
2099  0 toggle @Override
2100    public void assertInvokeDynamic() {
2101    /* do nothing */
2102    }
2103   
 
2104  0 toggle @Override
2105    public void assertSubRoutine() {
2106    /* do nothing */
2107    }
2108   
 
2109  5 toggle @Override
2110    public void assertType(int modifier, boolean definesInterfaces, boolean isGeneric) {
2111  5 if (modifier != PackageDescription.PACKAGE_MODIFIERS) {
2112  0 throw new IllegalStateException("A package description type must define " + PackageDescription.PACKAGE_MODIFIERS + " as modifier");
2113  5 } else if (definesInterfaces) {
2114  1 throw new IllegalStateException("Cannot implement interface for package type");
2115    }
2116    }
2117   
 
2118  1 toggle @Override
2119    public String toString() {
2120  1 return "TypeWriter.Default.ValidatingClassVisitor.Constraint.ForPackageType." + name();
2121    }
2122    }
2123   
2124    /**
2125    * Represents the constraint of an interface type.
2126    */
 
2127    enum ForInterface implements Constraint {
2128   
2129    /**
2130    * An interface type with the constrains for the Java versions 5 to 7.
2131    */
2132    CLASSIC(true),
2133   
2134    /**
2135    * An interface type with the constrains for the Java versions 8+.
2136    */
2137    JAVA_8(false);
2138   
2139    /**
2140    * {@code true} if this instance represents a classic interface type (pre Java 8).
2141    */
2142    private final boolean classic;
2143   
2144    /**
2145    * Creates a constraint for an interface type.
2146    *
2147    * @param classic {@code true} if this instance represents a classic interface (pre Java 8).
2148    */
 
2149  2 toggle ForInterface(boolean classic) {
2150  2 this.classic = classic;
2151    }
2152   
 
2153  5 toggle @Override
2154    public void assertField(String name, boolean isPublic, boolean isStatic, boolean isGeneric) {
2155  5 if (!isStatic || !isPublic) {
2156  2 throw new IllegalStateException("Cannot define non-static or non-public field '" + name + "' for interface type");
2157    }
2158    }
2159   
 
2160  14 toggle @Override
2161    public void assertMethod(String name,
2162    boolean isAbstract,
2163    boolean isPublic,
2164    boolean isStatic,
2165    boolean isDefaultValueIncompatible,
2166    boolean isNonStaticNonVirtual,
2167    boolean isGeneric) {
2168  14 if (!name.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)) {
2169  12 if (!isPublic || isNonStaticNonVirtual) {
2170  3 throw new IllegalStateException("Cannot define non-public or non-virtual method '" + name + "' for interface type");
2171  9 } else if (classic && isStatic) {
2172  0 throw new IllegalStateException("Cannot define static method '" + name + "' for a pre-Java 8 interface type");
2173  9 } else if (classic && !isAbstract) {
2174  0 throw new IllegalStateException("Cannot define default method '" + name + "' for pre-Java 8 interface type");
2175    }
2176    }
2177    }
2178   
 
2179  0 toggle @Override
2180    public void assertAnnotation() {
2181    /* do nothing */
2182    }
2183   
 
2184  0 toggle @Override
2185    public void assertTypeAnnotation() {
2186    /* do nothing */
2187    }
2188   
 
2189  0 toggle @Override
2190    public void assertDefaultValue(String name) {
2191    /* do nothing */
2192    }
2193   
 
2194  15 toggle @Override
2195    public void assertType(int modifier, boolean definesInterfaces, boolean isGeneric) {
2196    /* do nothing */
2197    }
2198   
 
2199  0 toggle @Override
2200    public void assertTypeInConstantPool() {
2201    /* do nothing */
2202    }
2203   
 
2204  0 toggle @Override
2205    public void assertMethodTypeInConstantPool() {
2206    /* do nothing */
2207    }
2208   
 
2209  0 toggle @Override
2210    public void assertHandleInConstantPool() {
2211    /* do nothing */
2212    }
2213   
 
2214  0 toggle @Override
2215    public void assertInvokeDynamic() {
2216    /* do nothing */
2217    }
2218   
 
2219  0 toggle @Override
2220    public void assertSubRoutine() {
2221    /* do nothing */
2222    }
2223   
 
2224  2 toggle @Override
2225    public String toString() {
2226  2 return "TypeWriter.Default.ValidatingClassVisitor.Constraint.ForInterface." + name();
2227    }
2228    }
2229   
2230    /**
2231    * Represents the constraint of an annotation type.
2232    */
 
2233    enum ForAnnotation implements Constraint {
2234   
2235    /**
2236    * An annotation type with the constrains for the Java versions 5 to 7.
2237    */
2238    CLASSIC(true),
2239   
2240    /**
2241    * An annotation type with the constrains for the Java versions 8+.
2242    */
2243    JAVA_8(false);
2244   
2245    /**
2246    * {@code true} if this instance represents a classic annotation type (pre Java 8).
2247    */
2248    private final boolean classic;
2249   
2250    /**
2251    * Creates a constraint for an annotation type.
2252    *
2253    * @param classic {@code true} if this instance represents a classic annotation type (pre Java 8).
2254    */
 
2255  2 toggle ForAnnotation(boolean classic) {
2256  2 this.classic = classic;
2257    }
2258   
 
2259  2 toggle @Override
2260    public void assertField(String name, boolean isPublic, boolean isStatic, boolean isGeneric) {
2261  2 if (!isStatic || !isPublic) {
2262  2 throw new IllegalStateException("Cannot define non-static or non-public field '" + name + "' for annotation type");
2263    }
2264    }
2265   
 
2266  12 toggle @Override
2267    public void assertMethod(String name,
2268    boolean isAbstract,
2269    boolean isPublic,
2270    boolean isStatic,
2271    boolean isDefaultValueIncompatible,
2272    boolean isNonStaticNonVirtual,
2273    boolean isGeneric) {
2274  12 if (!name.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)) {
2275  11 if (!isPublic || isNonStaticNonVirtual) {
2276  2 throw new IllegalStateException("Cannot define non-public, non-abstract or non-virtual method '" + name + "' for annotation type");
2277  9 } else if (classic && isStatic) {
2278  1 throw new IllegalStateException("Cannot define static method '" + name + "' for a pre-Java 8 annotation type");
2279  8 } else if (!isStatic && isDefaultValueIncompatible) {
2280  2 throw new IllegalStateException("Cannot define method '" + name + "' with the given signature as an annotation type method");
2281    }
2282    }
2283    }
2284   
 
2285  0 toggle @Override
2286    public void assertAnnotation() {
2287    /* do nothing */
2288    }
2289   
 
2290  0 toggle @Override
2291    public void assertTypeAnnotation() {
2292    /* do nothing */
2293    }
2294   
 
2295  4 toggle @Override
2296    public void assertDefaultValue(String name) {
2297    /* do nothing */
2298    }
2299   
 
2300  12 toggle @Override
2301    public void assertType(int modifier, boolean definesInterfaces, boolean isGeneric) {
2302  12 if ((modifier & Opcodes.ACC_INTERFACE) == 0) {
2303  0 throw new IllegalStateException("Cannot define annotation type without interface modifier");
2304    }
2305    }
2306   
 
2307  0 toggle @Override
2308    public void assertTypeInConstantPool() {
2309    /* do nothing */
2310    }
2311   
 
2312  0 toggle @Override
2313    public void assertMethodTypeInConstantPool() {
2314    /* do nothing */
2315    }
2316   
 
2317  0 toggle @Override
2318    public void assertHandleInConstantPool() {
2319    /* do nothing */
2320    }
2321   
 
2322  0 toggle @Override
2323    public void assertInvokeDynamic() {
2324    /* do nothing */
2325    }
2326   
 
2327  0 toggle @Override
2328    public void assertSubRoutine() {
2329    /* do nothing */
2330    }
2331   
 
2332  2 toggle @Override
2333    public String toString() {
2334  2 return "TypeWriter.Default.ValidatingClassVisitor.Constraint.ForAnnotation." + name();
2335    }
2336    }
2337   
2338    /**
2339    * Represents the constraint implied by a class file version.
2340    */
 
2341    class ForClassFileVersion implements Constraint {
2342   
2343    /**
2344    * The enforced class file version.
2345    */
2346    private final ClassFileVersion classFileVersion;
2347   
2348    /**
2349    * Creates a new constraint for the given class file version.
2350    *
2351    * @param classFileVersion The enforced class file version.
2352    */
 
2353  1435 toggle public ForClassFileVersion(ClassFileVersion classFileVersion) {
2354  1435 this.classFileVersion = classFileVersion;
2355    }
2356   
 
2357  1431 toggle @Override
2358    public void assertType(int modifiers, boolean definesInterfaces, boolean isGeneric) {
2359  1431 if ((modifiers & Opcodes.ACC_ANNOTATION) != 0 && !classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) {
2360  0 throw new IllegalStateException("Cannot define annotation type for class file version " + classFileVersion);
2361  1431 } else if (isGeneric && !classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) {
2362  0 throw new IllegalStateException("Cannot define a generic type for class file version " + classFileVersion);
2363    }
2364    }
2365   
 
2366  1798 toggle @Override
2367    public void assertField(String name, boolean isPublic, boolean isStatic, boolean isGeneric) {
2368  1798 if (isGeneric && !classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) {
2369  0 throw new IllegalStateException("Cannot define generic field '" + name + "' for class file version " + classFileVersion);
2370    }
2371    }
2372   
 
2373  4359 toggle @Override
2374    public void assertMethod(String name,
2375    boolean isAbstract,
2376    boolean isPublic,
2377    boolean isStatic,
2378    boolean isDefaultValueIncompatible,
2379    boolean isNonStaticNonVirtual,
2380    boolean isGeneric) {
2381  4359 if (isGeneric && !classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) {
2382  0 throw new IllegalStateException("Cannot define generic method '" + name + "' for class file version " + classFileVersion);
2383  4359 } else if ((isStatic || isNonStaticNonVirtual) && isAbstract) {
2384  4 throw new IllegalStateException("Cannot define static or non-virtual method '" + name + "' to be abstract");
2385    }
2386    }
2387   
 
2388  258 toggle @Override
2389    public void assertAnnotation() {
2390  258 if (!classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) {
2391  3 throw new IllegalStateException("Cannot write annotations for class file version " + classFileVersion);
2392    }
2393    }
2394   
 
2395  39 toggle @Override
2396    public void assertTypeAnnotation() {
2397  39 if (!classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) {
2398  0 throw new IllegalStateException("Cannot write type annotations for class file version " + classFileVersion);
2399    }
2400    }
2401   
 
2402  4 toggle @Override
2403    public void assertDefaultValue(String name) {
2404    /* do nothing, implicitly checked by type assertion */
2405    }
2406   
 
2407  813 toggle @Override
2408    public void assertTypeInConstantPool() {
2409  813 if (!classFileVersion.isAtLeast(ClassFileVersion.JAVA_V5)) {
2410  0 throw new IllegalStateException("Cannot write type to constant pool for class file version " + classFileVersion);
2411    }
2412    }
2413   
 
2414  11 toggle @Override
2415    public void assertMethodTypeInConstantPool() {
2416  11 if (!classFileVersion.isAtLeast(ClassFileVersion.JAVA_V7)) {
2417  1 throw new IllegalStateException("Cannot write method type to constant pool for class file version " + classFileVersion);
2418    }
2419    }
2420   
 
2421  11 toggle @Override
2422    public void assertHandleInConstantPool() {
2423  11 if (!classFileVersion.isAtLeast(ClassFileVersion.JAVA_V7)) {
2424  1 throw new IllegalStateException("Cannot write method handle to constant pool for class file version " + classFileVersion);
2425    }
2426    }
2427   
 
2428  21 toggle @Override
2429    public void assertInvokeDynamic() {
2430  21 if (!classFileVersion.isAtLeast(ClassFileVersion.JAVA_V7)) {
2431  0 throw new IllegalStateException("Cannot write invoke dynamic instruction for class file version " + classFileVersion);
2432    }
2433    }
2434   
 
2435  0 toggle @Override
2436    public void assertSubRoutine() {
2437  0 if (!classFileVersion.isLessThan(ClassFileVersion.JAVA_V6)) {
2438  0 throw new IllegalStateException("Cannot write subroutine for class file version " + classFileVersion);
2439    }
2440    }
2441   
 
2442  5 toggle @Override
2443    public boolean equals(Object other) {
2444  5 return this == other || !(other == null || getClass() != other.getClass())
2445    && classFileVersion.equals(((ForClassFileVersion) other).classFileVersion);
2446    }
2447   
 
2448  3 toggle @Override
2449    public int hashCode() {
2450  3 return classFileVersion.hashCode();
2451    }
2452   
 
2453  3 toggle @Override
2454    public String toString() {
2455  3 return "TypeWriter.Default.ValidatingClassVisitor.Constraint.ForClassFileVersion{" +
2456    "classFileVersion=" + classFileVersion +
2457    '}';
2458    }
2459    }
2460   
2461    /**
2462    * A constraint implementation that summarizes several constraints.
2463    */
 
2464    class Compound implements Constraint {
2465   
2466    /**
2467    * A list of constraints that is enforced in the given order.
2468    */
2469    private final List<? extends Constraint> constraints;
2470   
2471    /**
2472    * Creates a new compound constraint.
2473    *
2474    * @param constraints A list of constraints that is enforced in the given order.
2475    */
 
2476  1434 toggle public Compound(List<? extends Constraint> constraints) {
2477  1434 this.constraints = constraints;
2478    }
2479   
 
2480  1798 toggle @Override
2481    public void assertField(String name, boolean isPublic, boolean isStatic, boolean isGeneric) {
2482  1798 for (Constraint constraint : constraints) {
2483  3596 constraint.assertField(name, isPublic, isStatic, isGeneric);
2484    }
2485    }
2486   
 
2487  4359 toggle @Override
2488    public void assertMethod(String name,
2489    boolean isAbstract,
2490    boolean isPublic,
2491    boolean isStatic,
2492    boolean isDefaultValueIncompatible,
2493    boolean isNonStaticNonVirtual,
2494    boolean isGeneric) {
2495  4359 for (Constraint constraint : constraints) {
2496  8714 constraint.assertMethod(name,
2497    isAbstract,
2498    isPublic,
2499    isStatic,
2500    isDefaultValueIncompatible,
2501    isNonStaticNonVirtual,
2502    isGeneric);
2503    }
2504    }
2505   
 
2506  4 toggle @Override
2507    public void assertDefaultValue(String name) {
2508  4 for (Constraint constraint : constraints) {
2509  8 constraint.assertDefaultValue(name);
2510    }
2511    }
2512   
 
2513  258 toggle @Override
2514    public void assertAnnotation() {
2515  258 for (Constraint constraint : constraints) {
2516  513 constraint.assertAnnotation();
2517    }
2518    }
2519   
 
2520  39 toggle @Override
2521    public void assertTypeAnnotation() {
2522  39 for (Constraint constraint : constraints) {
2523  78 constraint.assertTypeAnnotation();
2524    }
2525    }
2526   
 
2527  1431 toggle @Override
2528    public void assertType(int modifier, boolean definesInterfaces, boolean isGeneric) {
2529  1431 for (Constraint constraint : constraints) {
2530  2862 constraint.assertType(modifier, definesInterfaces, isGeneric);
2531    }
2532    }
2533   
 
2534  813 toggle @Override
2535    public void assertTypeInConstantPool() {
2536  813 for (Constraint constraint : constraints) {
2537  1626 constraint.assertTypeInConstantPool();
2538    }
2539    }
2540   
 
2541  11 toggle @Override
2542    public void assertMethodTypeInConstantPool() {
2543  11 for (Constraint constraint : constraints) {
2544  21 constraint.assertMethodTypeInConstantPool();
2545    }
2546    }
2547   
 
2548  11 toggle @Override
2549    public void assertHandleInConstantPool() {
2550  11 for (Constraint constraint : constraints) {
2551  21 constraint.assertHandleInConstantPool();
2552    }
2553    }
2554   
 
2555  21 toggle @Override
2556    public void assertInvokeDynamic() {
2557  21 for (Constraint constraint : constraints) {
2558  42 constraint.assertInvokeDynamic();
2559    }
2560    }
2561   
 
2562  0 toggle @Override
2563    public void assertSubRoutine() {
2564  0 for (Constraint constraint : constraints) {
2565  0 constraint.assertSubRoutine();
2566    }
2567    }
2568   
 
2569  5 toggle @Override
2570    public boolean equals(Object other) {
2571  5 return this == other || !(other == null || getClass() != other.getClass())
2572    && constraints.equals(((Compound) other).constraints);
2573    }
2574   
 
2575  3 toggle @Override
2576    public int hashCode() {
2577  3 return constraints.hashCode();
2578    }
2579   
 
2580  3 toggle @Override
2581    public String toString() {
2582  3 return "TypeWriter.Default.ValidatingClassVisitor.Constraint.Compound{" +
2583    "constraints=" + constraints +
2584    '}';
2585    }
2586    }
2587    }
2588   
2589    /**
2590    * A field validator for checking default values.
2591    */
 
2592    protected class ValidatingFieldVisitor extends FieldVisitor {
2593   
2594    /**
2595    * Creates a validating field visitor.
2596    *
2597    * @param fieldVisitor The field visitor to which any calls are delegated to.
2598    */
 
2599  1795 toggle protected ValidatingFieldVisitor(FieldVisitor fieldVisitor) {
2600  1795 super(Opcodes.ASM5, fieldVisitor);
2601    }
2602   
 
2603  7 toggle @Override
2604    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
2605  7 constraint.assertAnnotation();
2606  6 return super.visitAnnotation(desc, visible);
2607    }
2608   
 
2609  2 toggle @Override
2610    public String toString() {
2611  2 return "TypeWriter.Default.ValidatingClassVisitor.ValidatingFieldVisitor{" +
2612    "classVisitor=" + ValidatingClassVisitor.this +
2613    '}';
2614    }
2615    }
2616   
2617    /**
2618    * A method validator for checking default values.
2619    */
 
2620    protected class ValidatingMethodVisitor extends MethodVisitor {
2621   
2622    /**
2623    * The name of the method being visited.
2624    */
2625    private final String name;
2626   
2627    /**
2628    * Creates a validating method visitor.
2629    *
2630    * @param methodVisitor The method visitor to which any calls are delegated to.
2631    * @param name The name of the method being visited.
2632    */
 
2633  4346 toggle protected ValidatingMethodVisitor(MethodVisitor methodVisitor, String name) {
2634  4346 super(Opcodes.ASM5, methodVisitor);
2635  4346 this.name = name;
2636    }
2637   
 
2638  174 toggle @Override
2639    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
2640  174 constraint.assertAnnotation();
2641  173 return super.visitAnnotation(desc, visible);
2642    }
2643   
 
2644  4 toggle @Override
2645    public AnnotationVisitor visitAnnotationDefault() {
2646  4 constraint.assertDefaultValue(name);
2647  4 return super.visitAnnotationDefault();
2648    }
2649   
 
2650  4152 toggle @Override
2651    @SuppressFBWarnings(value = "SF_SWITCH_NO_DEFAULT", justification = "Fall through to default case is intentional")
2652    public void visitLdcInsn(Object constant) {
2653  4152 if (constant instanceof Type) {
2654  824 Type type = (Type) constant;
2655  824 switch (type.getSort()) {
2656  813 case Type.OBJECT:
2657  0 case Type.ARRAY:
2658  813 constraint.assertTypeInConstantPool();
2659  813 break;
2660  11 case Type.METHOD:
2661  11 constraint.assertMethodTypeInConstantPool();
2662  10 break;
2663    }
2664  3328 } else if (constant instanceof Handle) {
2665  11 constraint.assertHandleInConstantPool();
2666    }
2667  4150 super.visitLdcInsn(constant);
2668    }
2669   
 
2670  21 toggle @Override
2671    public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethod, Object... bootstrapArgument) {
2672  21 constraint.assertInvokeDynamic();
2673  21 super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethod, bootstrapArgument);
2674    }
2675   
 
2676  19294 toggle @Override
2677    public void visitJumpInsn(int opcode, Label label) {
2678  19294 if (opcode == Opcodes.JSR) {
2679  0 constraint.assertSubRoutine();
2680    }
2681  19294 super.visitJumpInsn(opcode, label);
2682    }
2683   
 
2684  4 toggle @Override
2685    public String toString() {
2686  4 return "TypeWriter.Default.ValidatingClassVisitor.ValidatingMethodVisitor{" +
2687    "classVisitor=" + ValidatingClassVisitor.this +
2688    ", name='" + name + '\'' +
2689    '}';
2690    }
2691    }
2692    }
2693   
2694    /**
2695    * A class writer that piggy-backs on Byte Buddy's {@link ClassFileLocator} to avoid class loading or look-up errors when redefining a class.
2696    * This is not available when creating a new class where automatic frame computation is however not normally a requirement.
2697    */
 
2698    protected static class FrameComputingClassWriter extends ClassWriter {
2699   
2700    /**
2701    * The type pool to use for computing stack map frames, if required.
2702    */
2703    private final TypePool typePool;
2704   
2705    /**
2706    * Creates a new frame computing class writer.
2707    *
2708    * @param flags The flags to be handed to the writer.
2709    * @param typePool The type pool to use for computing stack map frames, if required.
2710    */
 
2711  901 toggle protected FrameComputingClassWriter(int flags, TypePool typePool) {
2712  901 super(flags);
2713  901 this.typePool = typePool;
2714    }
2715   
2716    /**
2717    * Creates a new frame computing class writer.
2718    *
2719    * @param classReader The class reader from which the original class is read.
2720    * @param flags The flags to be handed to the writer.
2721    * @param typePool The type pool to use for computing stack map frames, if required.
2722    */
 
2723  573 toggle protected FrameComputingClassWriter(ClassReader classReader, int flags, TypePool typePool) {
2724  573 super(classReader, flags);
2725  573 this.typePool = typePool;
2726    }
2727   
 
2728  5 toggle @Override
2729    protected String getCommonSuperClass(String leftTypeName, String rightTypeName) {
2730  5 TypeDescription leftType = typePool.describe(leftTypeName.replace('/', '.')).resolve();
2731  5 TypeDescription rightType = typePool.describe(rightTypeName.replace('/', '.')).resolve();
2732  5 if (leftType.isAssignableFrom(rightType)) {
2733  1 return leftType.getInternalName();
2734  4 } else if (leftType.isAssignableTo(rightType)) {
2735  1 return rightType.getInternalName();
2736  3 } else if (leftType.isInterface() || rightType.isInterface()) {
2737  2 return TypeDescription.OBJECT.getInternalName();
2738    } else {
2739  1 do {
2740  1 leftType = leftType.getSuperClass().asErasure();
2741  1 } while (!leftType.isAssignableFrom(rightType));
2742  1 return leftType.getInternalName();
2743    }
2744    }
2745   
 
2746  10 toggle @Override
2747    public String toString() {
2748  10 return "TypeWriter.Default.FrameComputingClassWriter{" +
2749    "typePool=" + typePool +
2750    '}';
2751    }
2752    }
2753   
2754    /**
2755    * A type writer that inlines the created type into an existing class file.
2756    *
2757    * @param <U> The best known loaded type for the dynamically created type.
2758    */
 
2759    public static class ForInlining<U> extends Default<U> {
2760   
2761    /**
2762    * Indicates that a method should be ignored.
2763    */
2764    private static final MethodVisitor IGNORE_METHOD = null;
2765   
2766    /**
2767    * Indicates that an annotation should be ignored.
2768    */
2769    private static final AnnotationVisitor IGNORE_ANNOTATION = null;
2770   
2771    /**
2772    * The original type that is being redefined or rebased.
2773    */
2774    private final TypeDescription originalType;
2775   
2776    /**
2777    * The class file locator for locating the original type's class file.
2778    */
2779    private final ClassFileLocator classFileLocator;
2780   
2781    /**
2782    * The method rebase resolver to use for rebasing methods.
2783    */
2784    private final MethodRebaseResolver methodRebaseResolver;
2785   
2786    /**
2787    * Creates a new default type writer for creating a new type that is not based on an existing class file.
2788    *
2789    * @param instrumentedType The instrumented type to be created.
2790    * @param fieldPool The field pool to use.
2791    * @param methodPool The method pool to use.
2792    * @param explicitAuxiliaryTypes The explicit auxiliary types to add to the created type.
2793    * @param instrumentedMethods The instrumented methods relevant to this type creation.
2794    * @param loadedTypeInitializer The loaded type initializer to apply onto the created type after loading.
2795    * @param typeInitializer The type initializer to include in the created type's type initializer.
2796    * @param typeAttributeAppender The type attribute appender to apply onto the instrumented type.
2797    * @param asmVisitorWrapper The ASM visitor wrapper to apply onto the class writer.
2798    * @param classFileVersion The class file version to define auxiliary types in.
2799    * @param annotationValueFilterFactory The annotation value filter factory to apply.
2800    * @param annotationRetention The annotation retention to apply.
2801    * @param auxiliaryTypeNamingStrategy The naming strategy for auxiliary types to apply.
2802    * @param implementationContextFactory The implementation context factory to apply.
2803    * @param typeValidation Determines if a type should be explicitly validated.
2804    * @param typePool The type pool to use for computing stack map frames, if required.
2805    * @param originalType The original type that is being redefined or rebased.
2806    * @param classFileLocator The class file locator for locating the original type's class file.
2807    * @param methodRebaseResolver The method rebase resolver to use for rebasing methods.
2808    */
 
2809  586 toggle protected ForInlining(TypeDescription instrumentedType,
2810    FieldPool fieldPool,
2811    MethodPool methodPool,
2812    List<DynamicType> explicitAuxiliaryTypes,
2813    MethodList<?> instrumentedMethods,
2814    LoadedTypeInitializer loadedTypeInitializer,
2815    TypeInitializer typeInitializer,
2816    TypeAttributeAppender typeAttributeAppender,
2817    AsmVisitorWrapper asmVisitorWrapper,
2818    ClassFileVersion classFileVersion,
2819    AnnotationValueFilter.Factory annotationValueFilterFactory,
2820    AnnotationRetention annotationRetention,
2821    AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
2822    Implementation.Context.Factory implementationContextFactory,
2823    TypeValidation typeValidation,
2824    TypePool typePool,
2825    TypeDescription originalType,
2826    ClassFileLocator classFileLocator,
2827    MethodRebaseResolver methodRebaseResolver) {
2828  586 super(instrumentedType,
2829    fieldPool,
2830    methodPool,
2831    explicitAuxiliaryTypes,
2832    instrumentedMethods,
2833    loadedTypeInitializer,
2834    typeInitializer,
2835    typeAttributeAppender,
2836    asmVisitorWrapper,
2837    classFileVersion,
2838    annotationValueFilterFactory,
2839    annotationRetention,
2840    auxiliaryTypeNamingStrategy,
2841    implementationContextFactory,
2842    typeValidation,
2843    typePool);
2844  586 this.originalType = originalType;
2845  586 this.classFileLocator = classFileLocator;
2846  586 this.methodRebaseResolver = methodRebaseResolver;
2847    }
2848   
 
2849  565 toggle @Override
2850    public byte[] create(Implementation.Context.ExtractableView implementationContext) {
2851  565 try {
2852  565 ClassFileLocator.Resolution resolution = classFileLocator.locate(originalType.getName());
2853  565 if (!resolution.isResolved()) {
2854  0 throw new IllegalArgumentException("Cannot locate the class file for " + originalType + " using " + classFileLocator);
2855    }
2856  565 return doCreate(implementationContext, resolution.resolve());
2857    } catch (IOException exception) {
2858  0 throw new RuntimeException("The class file could not be written", exception);
2859    }
2860    }
2861   
2862    /**
2863    * Performs the actual creation of a class file.
2864    *
2865    * @param implementationContext The implementation context to use for implementing the class file.
2866    * @param binaryRepresentation The binary representation of the class file.
2867    * @return The byte array representing the created class.
2868    */
 
2869  565 toggle private byte[] doCreate(Implementation.Context.ExtractableView implementationContext, byte[] binaryRepresentation) {
2870  565 int writerFlags = asmVisitorWrapper.mergeWriter(AsmVisitorWrapper.NO_FLAGS), readerFlags = asmVisitorWrapper.mergeReader(AsmVisitorWrapper.NO_FLAGS);
2871  565 ClassReader classReader = new ClassReader(binaryRepresentation);
2872  565 ClassWriter classWriter = new FrameComputingClassWriter(classReader, writerFlags, typePool);
2873  565 classReader.accept(writeTo(asmVisitorWrapper.wrap(instrumentedType,
2874    ValidatingClassVisitor.of(classWriter, typeValidation),
2875    writerFlags,
2876    readerFlags), implementationContext), readerFlags);
2877  526 return classWriter.toByteArray();
2878    }
2879   
2880    /**
2881    * Creates a class visitor which weaves all changes and additions on the fly.
2882    *
2883    * @param classVisitor The class visitor to which this entry is to be written to.
2884    * @param implementationContext The implementation context to use for implementing the class file.
2885    * @return A class visitor which is capable of applying the changes.
2886    */
 
2887  565 toggle private ClassVisitor writeTo(ClassVisitor classVisitor, Implementation.Context.ExtractableView implementationContext) {
2888  565 return originalType.getName().equals(instrumentedType.getName())
2889    ? new RedefinitionClassVisitor(classVisitor, implementationContext)
2890    : new ClassRemapper(new RedefinitionClassVisitor(classVisitor, implementationContext), new SimpleRemapper(originalType.getInternalName(), instrumentedType.getInternalName()));
2891    }
2892   
 
2893  23 toggle @Override
2894    public boolean equals(Object other) {
2895  1 if (this == other) return true;
2896  2 if (other == null || getClass() != other.getClass()) return false;
2897  16 if (!super.equals(other)) return false;
2898  4 ForInlining<?> that = (ForInlining<?>) other;
2899  4 return originalType.equals(that.originalType)
2900    && classFileLocator.equals(that.classFileLocator)
2901    && methodRebaseResolver.equals(that.methodRebaseResolver);
2902    }
2903   
 
2904  21 toggle @Override
2905    public int hashCode() {
2906  21 int result = super.hashCode();
2907  21 result = 31 * result + originalType.hashCode();
2908  21 result = 31 * result + classFileLocator.hashCode();
2909  21 result = 31 * result + methodRebaseResolver.hashCode();
2910  21 return result;
2911    }
2912   
 
2913  8 toggle @Override
2914    public String toString() {
2915  8 return "TypeWriter.Default.ForInlining{" +
2916    "instrumentedType=" + instrumentedType +
2917    ", fieldPool=" + fieldPool +
2918    ", methodPool=" + methodPool +
2919    ", explicitAuxiliaryTypes=" + explicitAuxiliaryTypes +
2920    ", instrumentedMethods=" + instrumentedMethods +
2921    ", loadedTypeInitializer=" + loadedTypeInitializer +
2922    ", typeInitializer=" + typeInitializer +
2923    ", typeAttributeAppender=" + typeAttributeAppender +
2924    ", asmVisitorWrapper=" + asmVisitorWrapper +
2925    ", classFileVersion=" + classFileVersion +
2926    ", annotationValueFilterFactory=" + annotationValueFilterFactory +
2927    ", annotationRetention=" + annotationRetention +
2928    ", auxiliaryTypeNamingStrategy=" + auxiliaryTypeNamingStrategy +
2929    ", implementationContextFactory=" + implementationContextFactory +
2930    ", typeValidation=" + typeValidation +
2931    ", originalType=" + originalType +
2932    ", classFileLocator=" + classFileLocator +
2933    ", methodRebaseResolver=" + methodRebaseResolver +
2934    '}';
2935    }
2936   
2937    /**
2938    * A method containing the original type initializer of a redefined class.
2939    */
 
2940    protected static class TypeInitializerDelegate extends MethodDescription.InDefinedShape.AbstractBase {
2941   
2942    /**
2943    * A prefix for the name of the method that represents the original type initializer.
2944    */
2945    private static final String TYPE_INITIALIZER_PROXY_PREFIX = "classInitializer";
2946   
2947    /**
2948    * The instrumented type that defines this delegate method.
2949    */
2950    private final TypeDescription instrumentedType;
2951   
2952    /**
2953    * The suffix to append to the default prefix in order to avoid naming conflicts.
2954    */
2955    private final String suffix;
2956   
2957    /**
2958    * Creates a new type initializer delegate.
2959    *
2960    * @param instrumentedType The instrumented type that defines this delegate method.
2961    * @param suffix The suffix to append to the default prefix in order to avoid naming conflicts.
2962    */
 
2963  67 toggle protected TypeInitializerDelegate(TypeDescription instrumentedType, String suffix) {
2964  67 this.instrumentedType = instrumentedType;
2965  67 this.suffix = suffix;
2966    }
2967   
 
2968  67 toggle @Override
2969    public TypeDescription getDeclaringType() {
2970  67 return instrumentedType;
2971    }
2972   
 
2973  268 toggle @Override
2974    public ParameterList<ParameterDescription.InDefinedShape> getParameters() {
2975  268 return new ParameterList.Empty<ParameterDescription.InDefinedShape>();
2976    }
2977   
 
2978  402 toggle @Override
2979    public TypeDescription.Generic getReturnType() {
2980  402 return TypeDescription.Generic.VOID;
2981    }
2982   
 
2983  134 toggle @Override
2984    public TypeList.Generic getExceptionTypes() {
2985  134 return new TypeList.Generic.Empty();
2986    }
2987   
 
2988  0 toggle @Override
2989    public Object getDefaultValue() {
2990  0 return MethodDescription.NO_DEFAULT_VALUE;
2991    }
2992   
 
2993  67 toggle @Override
2994    public TypeList.Generic getTypeVariables() {
2995  67 return new TypeList.Generic.Empty();
2996    }
2997   
 
2998  67 toggle @Override
2999    public AnnotationList getDeclaredAnnotations() {
3000  67 return new AnnotationList.Empty();
3001    }
3002   
 
3003  268 toggle @Override
3004    public int getModifiers() {
3005  268 return Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC | (instrumentedType.isInterface()
3006    ? Opcodes.ACC_PUBLIC
3007    : Opcodes.ACC_PRIVATE);
3008    }
3009   
 
3010  201 toggle @Override
3011    public String getInternalName() {
3012  201 return String.format("%s$%s", TYPE_INITIALIZER_PROXY_PREFIX, suffix);
3013    }
3014    }
3015   
3016    /**
3017    * A class visitor which is capable of applying a redefinition of an existing class file.
3018    */
 
3019    protected class RedefinitionClassVisitor extends ClassVisitor {
3020   
3021    /**
3022    * The implementation context for this class creation.
3023    */
3024    private final Implementation.Context.ExtractableView implementationContext;
3025   
3026    /**
3027    * A mapping of fields to write by their names.
3028    */
3029    private final Map<String, FieldDescription> declaredFields;
3030   
3031    /**
3032    * A mapping of methods to write by a concatenation of internal name and descriptor.
3033    */
3034    private final Map<String, MethodDescription> declarableMethods;
3035   
3036    /**
3037    * A mutable reference for code that is to be injected into the actual type initializer, if any.
3038    * Usually, this represents an invocation of the actual type initializer that is found in the class
3039    * file which is relocated into a static method.
3040    */
3041    private Implementation.Context.ExtractableView.InjectedCode injectedCode;
3042   
3043    /**
3044    * Creates a class visitor which is capable of redefining an existent class on the fly.
3045    *
3046    * @param classVisitor The underlying class visitor to which writes are delegated.
3047    * @param implementationContext The implementation context to use for implementing the class file.
3048    */
 
3049  567 toggle protected RedefinitionClassVisitor(ClassVisitor classVisitor, Implementation.Context.ExtractableView implementationContext) {
3050  567 super(Opcodes.ASM5, classVisitor);
3051  567 this.implementationContext = implementationContext;
3052  567 List<? extends FieldDescription> fieldDescriptions = instrumentedType.getDeclaredFields();
3053  567 declaredFields = new HashMap<String, FieldDescription>();
3054  567 for (FieldDescription fieldDescription : fieldDescriptions) {
3055  1102 declaredFields.put(fieldDescription.getName(), fieldDescription);
3056    }
3057  567 declarableMethods = new HashMap<String, MethodDescription>();
3058  567 for (MethodDescription methodDescription : instrumentedMethods) {
3059  182 declarableMethods.put(methodDescription.getInternalName() + methodDescription.getDescriptor(), methodDescription);
3060    }
3061  567 injectedCode = Implementation.Context.ExtractableView.InjectedCode.None.INSTANCE;
3062    }
3063   
 
3064  565 toggle @Override
3065    public void visit(int classFileVersionNumber,
3066    int modifiers,
3067    String internalName,
3068    String genericSignature,
3069    String superClassInternalName,
3070    String[] interfaceTypeInternalName) {
3071  565 super.visit(classFileVersionNumber,
3072    instrumentedType.getActualModifiers((modifiers & Opcodes.ACC_SUPER) != 0 && !instrumentedType.isInterface()),
3073    instrumentedType.getInternalName(),
3074    instrumentedType.getGenericSignature(),
3075  565 (instrumentedType.getSuperClass() == null ?
3076    TypeDescription.OBJECT :
3077    instrumentedType.getSuperClass().asErasure()).getInternalName(),
3078    instrumentedType.getInterfaces().asErasures().toInternalNames());
3079  565 implementationContext.setClassFileVersion(ClassFileVersion.ofMinorMajor(classFileVersionNumber));
3080  565 typeAttributeAppender.apply(cv, instrumentedType, annotationValueFilterFactory.on(instrumentedType));
3081  565 if (!ClassFileVersion.ofMinorMajor(classFileVersionNumber).isAtLeast(ClassFileVersion.JAVA_V8) && instrumentedType.isInterface()) {
3082  5 implementationContext.prohibitTypeInitializer();
3083    }
3084    }
3085   
 
3086  1507 toggle @Override
3087    public void visitInnerClass(String internalName, String outerName, String innerName, int modifiers) {
3088  1507 if (internalName.equals(instrumentedType.getInternalName())) {
3089  463 modifiers = instrumentedType.getModifiers();
3090    }
3091  1507 super.visitInnerClass(internalName, outerName, innerName, modifiers);
3092    }
3093   
 
3094  8 toggle @Override
3095    public AnnotationVisitor visitTypeAnnotation(int typeReference, TypePath typePath, String descriptor, boolean visible) {
3096  8 return annotationRetention.isEnabled()
3097    ? super.visitTypeAnnotation(typeReference, typePath, descriptor, visible)
3098    : IGNORE_ANNOTATION;
3099    }
3100   
 
3101  73 toggle @Override
3102    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
3103  73 return annotationRetention.isEnabled()
3104    ? super.visitAnnotation(descriptor, visible)
3105    : IGNORE_ANNOTATION;
3106    }
3107   
 
3108  1029 toggle @Override
3109    public FieldVisitor visitField(int modifiers,
3110    String internalName,
3111    String descriptor,
3112    String genericSignature,
3113    Object defaultValue) {
3114  1029 FieldDescription fieldDescription = declaredFields.remove(internalName);
3115  1029 if (fieldDescription != null) {
3116  1029 FieldPool.Record record = fieldPool.target(fieldDescription);
3117  1029 if (!record.isImplicit()) {
3118  6 return redefine(record, defaultValue);
3119    }
3120    }
3121  1023 return super.visitField(modifiers, internalName, descriptor, genericSignature, defaultValue);
3122    }
3123   
3124    /**
3125    * Redefines a field using the given explicit field pool record and default value.
3126    *
3127    * @param record The field pool value to apply during visitation of the existing field.
3128    * @param defaultValue The default value to write onto the field which might be {@code null}.
3129    * @return A field visitor for visiting the existing field definition.
3130    */
 
3131  6 toggle protected FieldVisitor redefine(FieldPool.Record record, Object defaultValue) {
3132  6 FieldDescription instrumentedField = record.getField();
3133  6 return new AttributeObtainingFieldVisitor(super.visitField(instrumentedField.getActualModifiers(),
3134    instrumentedField.getInternalName(),
3135    instrumentedField.getDescriptor(),
3136    instrumentedField.getGenericSignature(),
3137    record.resolveDefault(defaultValue)), record);
3138    }
3139   
 
3140  1821 toggle @Override
3141    public MethodVisitor visitMethod(int modifiers,
3142    String internalName,
3143    String descriptor,
3144    String genericSignature,
3145    String[] exceptionTypeInternalName) {
3146  1821 if (internalName.equals(MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME)) {
3147  103 if (implementationContext.isRetainTypeInitializer()) {
3148  36 return super.visitMethod(modifiers, internalName, descriptor, genericSignature, exceptionTypeInternalName);
3149    } else {
3150  67 TypeInitializerInjection injectedCode = new TypeInitializerInjection(new TypeInitializerDelegate(instrumentedType, RandomString.make()));
3151  67 this.injectedCode = injectedCode;
3152  67 return super.visitMethod(injectedCode.getInjectorProxyMethod().getActualModifiers(),
3153    injectedCode.getInjectorProxyMethod().getInternalName(),
3154    injectedCode.getInjectorProxyMethod().getDescriptor(),
3155    injectedCode.getInjectorProxyMethod().getGenericSignature(),
3156    injectedCode.getInjectorProxyMethod().getExceptionTypes().asErasures().toInternalNames());
3157    }
3158    }
3159  1718 MethodDescription methodDescription = declarableMethods.remove(internalName + descriptor);
3160  1718 return methodDescription == null
3161    ? super.visitMethod(modifiers, internalName, descriptor, genericSignature, exceptionTypeInternalName)
3162    : redefine(methodDescription, (modifiers & Opcodes.ACC_ABSTRACT) != 0);
3163    }
3164   
3165    /**
3166    * Redefines a given method if this is required by looking up a potential implementation from the
3167    * {@link net.bytebuddy.dynamic.scaffold.TypeWriter.MethodPool}.
3168    *
3169    * @param methodDescription The method being considered for redefinition.
3170    * @param abstractOrigin {@code true} if the original method is abstract, i.e. there is no implementation
3171    * to preserve.
3172    * @return A method visitor which is capable of consuming the original method.
3173    */
 
3174  113 toggle protected MethodVisitor redefine(MethodDescription methodDescription, boolean abstractOrigin) {
3175  113 MethodPool.Record record = methodPool.target(methodDescription);
3176  113 if (!record.getSort().isDefined()) {
3177  0 return super.visitMethod(methodDescription.getActualModifiers(),
3178    methodDescription.getInternalName(),
3179    methodDescription.getDescriptor(),
3180    methodDescription.getGenericSignature(),
3181    methodDescription.getExceptionTypes().asErasures().toInternalNames());
3182    }
3183  113 MethodDescription implementedMethod = record.getMethod();
3184  113 MethodVisitor methodVisitor = super.visitMethod(implementedMethod.getActualModifiers(record.getSort().isImplemented()),
3185    implementedMethod.getInternalName(),
3186    implementedMethod.getDescriptor(),
3187    implementedMethod.getGenericSignature(),
3188    implementedMethod.getExceptionTypes().asErasures().toInternalNames());
3189  113 return abstractOrigin
3190    ? new AttributeObtainingMethodVisitor(methodVisitor, record)
3191    : new CodePreservingMethodVisitor(methodVisitor, record, methodRebaseResolver.resolve(implementedMethod.asDefined()));
3192    }
3193   
 
3194  530 toggle @Override
3195    public void visitEnd() {
3196  530 for (FieldDescription fieldDescription : declaredFields.values()) {
3197  71 fieldPool.target(fieldDescription).apply(cv, annotationValueFilterFactory);
3198    }
3199  530 for (MethodDescription methodDescription : declarableMethods.values()) {
3200  69 methodPool.target(methodDescription).apply(cv, implementationContext, annotationValueFilterFactory);
3201    }
3202  529 implementationContext.drain(cv, methodPool, injectedCode, annotationValueFilterFactory);
3203  526 super.visitEnd();
3204    }
3205   
 
3206  10 toggle @Override
3207    public String toString() {
3208  10 return "TypeWriter.Default.ForInlining.RedefinitionClassVisitor{" +
3209    "typeWriter=" + TypeWriter.Default.ForInlining.this +
3210    ", implementationContext=" + implementationContext +
3211    ", declaredFields=" + declaredFields +
3212    ", declarableMethods=" + declarableMethods +
3213    ", injectedCode=" + injectedCode +
3214    '}';
3215    }
3216   
3217    /**
3218    * A field visitor that obtains all attributes and annotations of a field that is found in the
3219    * class file but that discards all code.
3220    */
 
3221    protected class AttributeObtainingFieldVisitor extends FieldVisitor {
3222   
3223    /**
3224    * The field pool record to apply onto the field visitor.
3225    */
3226    private final FieldPool.Record record;
3227   
3228    /**
3229    * Creates a new attribute obtaining field visitor.
3230    *
3231    * @param fieldVisitor The field visitor to delegate to.
3232    * @param record The field pool record to apply onto the field visitor.
3233    */
 
3234  8 toggle protected AttributeObtainingFieldVisitor(FieldVisitor fieldVisitor, FieldPool.Record record) {
3235  8 super(Opcodes.ASM5, fieldVisitor);
3236  8 this.record = record;
3237    }
3238   
 
3239  0 toggle @Override
3240    public AnnotationVisitor visitTypeAnnotation(int typeReference, TypePath typePath, String descriptor, boolean visible) {
3241  0 return annotationRetention.isEnabled()
3242    ? super.visitTypeAnnotation(typeReference, typePath, descriptor, visible)
3243    : IGNORE_ANNOTATION;
3244    }
3245   
 
3246  4 toggle @Override
3247    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
3248  4 return annotationRetention.isEnabled()
3249    ? super.visitAnnotation(descriptor, visible)
3250    : IGNORE_ANNOTATION;
3251    }
3252   
 
3253  6 toggle @Override
3254    public void visitEnd() {
3255  6 record.apply(fv, annotationValueFilterFactory);
3256  6 super.visitEnd();
3257    }
3258   
 
3259  4 toggle @Override
3260    public String toString() {
3261  4 return "TypeWriter.Default.ForInlining.RedefinitionClassVisitor.AttributeObtainingFieldVisitor{" +
3262    "classVisitor=" + TypeWriter.Default.ForInlining.RedefinitionClassVisitor.this +
3263    ", record=" + record +
3264    '}';
3265    }
3266    }
3267   
3268    /**
3269    * A method visitor that preserves the code of a method in the class file by copying it into a rebased
3270    * method while copying all attributes and annotations to the actual method.
3271    */
 
3272    protected class CodePreservingMethodVisitor extends MethodVisitor {
3273   
3274    /**
3275    * The method visitor of the actual method.
3276    */
3277    private final MethodVisitor actualMethodVisitor;
3278   
3279    /**
3280    * The method pool entry to apply.
3281    */
3282    private final MethodPool.Record record;
3283   
3284    /**
3285    * The resolution of a potential rebased method.
3286    */
3287    private final MethodRebaseResolver.Resolution resolution;
3288   
3289    /**
3290    * Creates a new code preserving method visitor.
3291    *
3292    * @param actualMethodVisitor The method visitor of the actual method.
3293    * @param record The method pool entry to apply.
3294    * @param resolution The resolution of the method rebase resolver in use.
3295    */
 
3296  113 toggle protected CodePreservingMethodVisitor(MethodVisitor actualMethodVisitor,
3297    MethodPool.Record record,
3298    MethodRebaseResolver.Resolution resolution) {
3299  113 super(Opcodes.ASM5, actualMethodVisitor);
3300  113 this.actualMethodVisitor = actualMethodVisitor;
3301  113 this.record = record;
3302  113 this.resolution = resolution;
3303  113 record.applyHead(actualMethodVisitor);
3304    }
3305   
 
3306  0 toggle @Override
3307    public AnnotationVisitor visitAnnotationDefault() {
3308  0 return IGNORE_ANNOTATION; // Annotation types can never be rebased.
3309    }
3310   
 
3311  0 toggle @Override
3312    public AnnotationVisitor visitTypeAnnotation(int typeReference, TypePath typePath, String descriptor, boolean visible) {
3313  0 return annotationRetention.isEnabled()
3314    ? super.visitTypeAnnotation(typeReference, typePath, descriptor, visible)
3315    : IGNORE_ANNOTATION;
3316    }
3317   
 
3318  5 toggle @Override
3319    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
3320  5 return annotationRetention.isEnabled()
3321    ? super.visitAnnotation(descriptor, visible)
3322    : IGNORE_ANNOTATION;
3323    }
3324   
 
3325  4 toggle @Override
3326    public AnnotationVisitor visitParameterAnnotation(int index, String descriptor, boolean visible) {
3327  4 return annotationRetention.isEnabled()
3328    ? super.visitParameterAnnotation(index, descriptor, visible)
3329    : IGNORE_ANNOTATION;
3330    }
3331   
 
3332  111 toggle @Override
3333    public void visitCode() {
3334  111 record.applyBody(actualMethodVisitor, implementationContext, annotationValueFilterFactory);
3335  111 actualMethodVisitor.visitEnd();
3336  111 mv = resolution.isRebased()
3337    ? cv.visitMethod(resolution.getResolvedMethod().getActualModifiers(),
3338    resolution.getResolvedMethod().getInternalName(),
3339    resolution.getResolvedMethod().getDescriptor(),
3340    resolution.getResolvedMethod().getGenericSignature(),
3341    resolution.getResolvedMethod().getExceptionTypes().asErasures().toInternalNames())
3342    : IGNORE_METHOD;
3343  111 super.visitCode();
3344    }
3345   
 
3346  111 toggle @Override
3347    public void visitMaxs(int stackSize, int localVariableLength) {
3348  111 super.visitMaxs(stackSize, Math.max(localVariableLength, resolution.getResolvedMethod().getStackSize()));
3349    }
3350   
 
3351  8 toggle @Override
3352    public String toString() {
3353  8 return "TypeWriter.Default.ForInlining.RedefinitionClassVisitor.CodePreservingMethodVisitor{" +
3354    "classVisitor=" + TypeWriter.Default.ForInlining.RedefinitionClassVisitor.this +
3355    ", actualMethodVisitor=" + actualMethodVisitor +
3356    ", record=" + record +
3357    ", resolution=" + resolution +
3358    '}';
3359    }
3360    }
3361   
3362    /**
3363    * A method visitor that obtains all attributes and annotations of a method that is found in the
3364    * class file but that discards all code.
3365    */
 
3366    protected class AttributeObtainingMethodVisitor extends MethodVisitor {
3367   
3368    /**
3369    * The method visitor to which the actual method is to be written to.
3370    */
3371    private final MethodVisitor actualMethodVisitor;
3372   
3373    /**
3374    * The method pool entry to apply.
3375    */
3376    private final MethodPool.Record record;
3377   
3378    /**
3379    * Creates a new attribute obtaining method visitor.
3380    *
3381    * @param actualMethodVisitor The method visitor of the actual method.
3382    * @param record The method pool entry to apply.
3383    */
 
3384  4 toggle protected AttributeObtainingMethodVisitor(MethodVisitor actualMethodVisitor, MethodPool.Record record) {
3385  4 super(Opcodes.ASM5, actualMethodVisitor);
3386  4 this.actualMethodVisitor = actualMethodVisitor;
3387  4 this.record = record;
3388  4 record.applyHead(actualMethodVisitor);
3389    }
3390   
 
3391  0 toggle @Override
3392    public AnnotationVisitor visitAnnotationDefault() {
3393  0 return IGNORE_ANNOTATION;
3394    }
3395   
 
3396  0 toggle @Override
3397    public AnnotationVisitor visitTypeAnnotation(int typeReference, TypePath typePath, String descriptor, boolean visible) {
3398  0 return annotationRetention.isEnabled()
3399    ? super.visitTypeAnnotation(typeReference, typePath, descriptor, visible)
3400    : IGNORE_ANNOTATION;
3401    }
3402   
 
3403  0 toggle @Override
3404    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
3405  0 return annotationRetention.isEnabled()
3406    ? super.visitAnnotation(descriptor, visible)
3407    : IGNORE_ANNOTATION;
3408    }
3409   
 
3410  0 toggle @Override
3411    public AnnotationVisitor visitParameterAnnotation(int index, String descriptor, boolean visible) {
3412  0 return annotationRetention.isEnabled()
3413    ? super.visitParameterAnnotation(index, descriptor, visible)
3414    : IGNORE_ANNOTATION;
3415    }
3416   
 
3417  0 toggle @Override
3418    public void visitCode() {
3419  0 mv = IGNORE_METHOD;
3420    }
3421   
 
3422  2 toggle @Override
3423    public void visitEnd() {
3424  2 record.applyBody(actualMethodVisitor, implementationContext, annotationValueFilterFactory);
3425  2 actualMethodVisitor.visitEnd();
3426    }
3427   
 
3428  6 toggle @Override
3429    public String toString() {
3430  6 return "TypeWriter.Default.ForInlining.RedefinitionClassVisitor.AttributeObtainingMethodVisitor{" +
3431    "classVisitor=" + TypeWriter.Default.ForInlining.RedefinitionClassVisitor.this +
3432    ", actualMethodVisitor=" + actualMethodVisitor +
3433    ", record=" + record +
3434    '}';
3435    }
3436    }
3437   
3438    /**
3439    * A code injection for the type initializer that invokes a method representing the original type initializer
3440    * which is copied to a static method.
3441    */
 
3442    protected class TypeInitializerInjection implements Implementation.Context.ExtractableView.InjectedCode {
3443   
3444    /**
3445    * The method to which the original type initializer code is to be written to.
3446    */
3447    private final MethodDescription injectorProxyMethod;
3448   
3449    /**
3450    * Creates a new type initializer injection.
3451    *
3452    * @param injectorProxyMethod The method to which the original type initializer code is to be written to.
3453    */
 
3454  69 toggle protected TypeInitializerInjection(MethodDescription injectorProxyMethod) {
3455  69 this.injectorProxyMethod = injectorProxyMethod;
3456    }
3457   
 
3458  67 toggle @Override
3459    public ByteCodeAppender getByteCodeAppender() {
3460  67 return new ByteCodeAppender.Simple(MethodInvocation.invoke(injectorProxyMethod));
3461    }
3462   
 
3463  67 toggle @Override
3464    public boolean isDefined() {
3465  67 return true;
3466    }
3467   
3468    /**
3469    * Returns the proxy method to which the original type initializer code is written to.
3470    *
3471    * @return A method description of this proxy method.
3472    */
 
3473  335 toggle public MethodDescription getInjectorProxyMethod() {
3474  335 return injectorProxyMethod;
3475    }
3476   
 
3477  3 toggle @Override
3478    public String toString() {
3479  3 return "TypeWriter.Default.ForInlining.RedefinitionClassVisitor.TypeInitializerInjection{" +
3480    "classVisitor=" + TypeWriter.Default.ForInlining.RedefinitionClassVisitor.this +
3481    ", injectorProxyMethod=" + injectorProxyMethod +
3482    '}';
3483    }
3484    }
3485    }
3486    }
3487   
3488    /**
3489    * A type writer that creates a class file that is not based upon another, existing class.
3490    *
3491    * @param <U> The best known loaded type for the dynamically created type.
3492    */
 
3493    public static class ForCreation<U> extends Default<U> {
3494   
3495    /**
3496    * Creates a new default type writer for creating a new type that is not based on an existing class file.
3497    *
3498    * @param instrumentedType The instrumented type to be created.
3499    * @param fieldPool The field pool to use.
3500    * @param methodPool The method pool to use.
3501    * @param explicitAuxiliaryTypes The explicit auxiliary types to add to the created type.
3502    * @param instrumentedMethods The instrumented methods relevant to this type creation.
3503    * @param loadedTypeInitializer The loaded type initializer to apply onto the created type after loading.
3504    * @param typeInitializer The type initializer to include in the created type's type initializer.
3505    * @param typeAttributeAppender The type attribute appender to apply onto the instrumented type.
3506    * @param asmVisitorWrapper The ASM visitor wrapper to apply onto the class writer.
3507    * @param classFileVersion The class file version to write the instrumented type in and to apply when creating auxiliary types.
3508    * @param annotationValueFilterFactory The annotation value filter factory to apply.
3509    * @param annotationRetention The annotation retention to apply.
3510    * @param auxiliaryTypeNamingStrategy The naming strategy for auxiliary types to apply.
3511    * @param implementationContextFactory The implementation context factory to apply.
3512    * @param typeValidation Determines if a type should be explicitly validated.
3513    * @param typePool The type pool to use for computing stack map frames, if required.
3514    */
 
3515  917 toggle protected ForCreation(TypeDescription instrumentedType,
3516    FieldPool fieldPool,
3517    MethodPool methodPool,
3518    List<DynamicType> explicitAuxiliaryTypes,
3519    MethodList<?> instrumentedMethods,
3520    LoadedTypeInitializer loadedTypeInitializer,
3521    TypeInitializer typeInitializer,
3522    TypeAttributeAppender typeAttributeAppender,
3523    AsmVisitorWrapper asmVisitorWrapper,
3524    ClassFileVersion classFileVersion,
3525    AnnotationValueFilter.Factory annotationValueFilterFactory,
3526    AnnotationRetention annotationRetention,
3527    AuxiliaryType.NamingStrategy auxiliaryTypeNamingStrategy,
3528    Implementation.Context.Factory implementationContextFactory,
3529    TypeValidation typeValidation,
3530    TypePool typePool) {
3531  917 super(instrumentedType,
3532    fieldPool,
3533    methodPool,
3534    explicitAuxiliaryTypes,
3535    instrumentedMethods,
3536    loadedTypeInitializer,
3537    typeInitializer,
3538    typeAttributeAppender,
3539    asmVisitorWrapper,
3540    classFileVersion,
3541    annotationValueFilterFactory,
3542    annotationRetention,
3543    auxiliaryTypeNamingStrategy,
3544    implementationContextFactory,
3545    typeValidation,
3546    typePool);
3547    }
3548   
 
3549  899 toggle @Override
3550    public byte[] create(Implementation.Context.ExtractableView implementationContext) {
3551  899 int writerFlags = asmVisitorWrapper.mergeWriter(AsmVisitorWrapper.NO_FLAGS);
3552  899 ClassWriter classWriter = new FrameComputingClassWriter(writerFlags, typePool);
3553  899 ClassVisitor classVisitor = asmVisitorWrapper.wrap(instrumentedType,
3554    ValidatingClassVisitor.of(classWriter, typeValidation),
3555    writerFlags,
3556    asmVisitorWrapper.mergeReader(AsmVisitorWrapper.NO_FLAGS));
3557  899 classVisitor.visit(classFileVersion.getMinorMajorVersion(),
3558    instrumentedType.getActualModifiers(!instrumentedType.isInterface()),
3559    instrumentedType.getInternalName(),
3560    instrumentedType.getGenericSignature(),
3561  899 (instrumentedType.getSuperClass() == null
3562    ? TypeDescription.OBJECT
3563    : instrumentedType.getSuperClass().asErasure()).getInternalName(),
3564    instrumentedType.getInterfaces().asErasures().toInternalNames());
3565  897 implementationContext.setClassFileVersion(classFileVersion);
3566  897 typeAttributeAppender.apply(classVisitor, instrumentedType, annotationValueFilterFactory.on(instrumentedType));
3567  896 for (FieldDescription fieldDescription : instrumentedType.getDeclaredFields()) {
3568  698 fieldPool.target(fieldDescription).apply(classVisitor, annotationValueFilterFactory);
3569    }
3570  887 for (MethodDescription methodDescription : instrumentedMethods) {
3571  2559 methodPool.target(methodDescription).apply(classVisitor, implementationContext, annotationValueFilterFactory);
3572    }
3573  808 implementationContext.drain(classVisitor, methodPool, Implementation.Context.ExtractableView.InjectedCode.None.INSTANCE, annotationValueFilterFactory);
3574  808 classVisitor.visitEnd();
3575  808 return classWriter.toByteArray();
3576    }
3577   
 
3578  2 toggle @Override
3579    public String toString() {
3580  2 return "TypeWriter.Default.ForCreation{" +
3581    "instrumentedType=" + instrumentedType +
3582    ", fieldPool=" + fieldPool +
3583    ", methodPool=" + methodPool +
3584    ", explicitAuxiliaryTypes=" + explicitAuxiliaryTypes +
3585    ", instrumentedMethods=" + instrumentedMethods +
3586    ", loadedTypeInitializer=" + loadedTypeInitializer +
3587    ", typeInitializer=" + typeInitializer +
3588    ", typeAttributeAppender=" + typeAttributeAppender +
3589    ", asmVisitorWrapper=" + asmVisitorWrapper +
3590    ", classFileVersion=" + classFileVersion +
3591    ", annotationValueFilterFactory=" + annotationValueFilterFactory +
3592    ", annotationRetention=" + annotationRetention +
3593    ", auxiliaryTypeNamingStrategy=" + auxiliaryTypeNamingStrategy +
3594    ", implementationContextFactory=" + implementationContextFactory +
3595    ", typeValidation=" + typeValidation +
3596    ", typePool=" + typePool +
3597    '}';
3598    }
3599    }
3600    }
3601    }